Experts:
First of all, many thanks to Arjan for putting together the first
draft of our spec -- it's an excellent start.
I've had a look at it, and have some comments/questions for
discussion. I think the biggest issues to resolve are probably:
- The interaction (or lack thereof) between
HttpAuthenticationMechanism and JASPIC.
- On a similar note, what is the behavior if
HttpAuthenticationMechanism is called both by the container
and by application code.
- How is SecurityContext integrated with containers such that
authenticate() can know what authentication mechanisms are
configured and getXYZ() can report the correct information?
- Is CallerPrincipal a sufficient credential for
IdentityStore.getGroupsByCallerPrincipal()? Can it be safely
used when there are multiple ID stores configured (since the
wrong groups could potentially be returned)?
- Related: should we define CallerAttributes in addition to
CallerGroups?
Any and all comments welcome.
Thanks,
Will
0.0 General
- Use of CDI vs. other mechanisms for accessing the interfaces
-- I think it's reasonable to say that containers must
use/support CDI in the ways described by the spec. (Am I correct
that all EE Profiles that include servlet would also include
CDI?) Is it worthwhile specifying that EE implementations can
optionally choose to make the interfaces available in some other
way (factory method, etc.)? Should we specify such a mechanism?
2.4 Installation
- Container should be able to override ID store contained within
app.
2.6 Validation and obtaining caller data
- Should the API support other types of user attributes beyond
groups? A generic attribute type?
- What if the information in a caller principal is insufficient
to distinguish the caller's identity (if, for example, the
credential provided when authenticating included a full DN, or a
duplicate username was disambiguated by virtue of the fact that
the password matched)? In that case, the correct groups could
not be determined. Should we limit the use of this to validate,
and require the caller to make use of the returned groups when
creating a subject, or retain the CredentialValidationResult?
- Would overloading actually work in this case, or would the
runtime always call validate(Credential) even if a Credential
sub-class type is passed? Might need generics for this.
- Last paragraph -- what if it can't, because it can't
distinguish between two foos, or because name is insufficient to
identify the user. Can (or should) an ID store support
getGroupsByCallerPrincipal() for a CallerPrincipal not
originally validated by that ID store?
2.7 Build-in Identity Store Beans
- Embedded -- annotation only? No support for deploying a file
or other mechanism? Safety of embedding passwords in file or in
code (annotation)?
- LDAP -- is annotation rich enough to support real-life
deployment requirements?
2.8. Handling multiple identity stores
- When validation fails, would it not be better to remember if
any of the identity stores accepted the credential, and return
INVALID instead of NOT_VALIDATED if any of them did?
- If we have a VALID result, won't we already have the groupsu
associated with the validate() that succeeded? Do we want to
aggregate groups from all stores, that return them, or return
only groups from the store that validated the user? I would
argue for the latter. This issue also complicates the provision
of a separate group lookup method when more than one id store is
present -- what if store A has a user foo, but validation fails.
Store B also has a user foo, which is validated with the
supplied credential. A subsequent call to get groups would
succeed for store A, but return groups for the wrong user (i.e,
the "foo" whose credential was not validated).
3.3 Relationship to other specs
3.4 Installation
- It must be possible to package an HttpAuthenticationMechanism
in an app, but can it be possible for server to override
app-provided mechanism?
- Should we define a web.xml token for indicating that an
HttpAuthenticationMechanism is in use, similar to BASIC, FORM,
CERT? (since the analogy is presented in section 3.3).
3.5 Orchestrating the authentication dialog
- Does validateRequest() get called twice, then, if called by
the container and again when the application calls
authenticate()? Must it therefore be idempotent?
- Should the ServerAuthModule's secureResponse() method be
called if the HttpAuthenticationMechanism's is?
- What happens if there is also a ServerAuthModule
installed/configured for the app? Are both mechanisms invoked
(it seems likely they'd interfere with each other)? How does,
e.g., an error returned from a ServerAuthModule affect the
subsequent invokation of the HttpAuthenticationMechanism?
- The JASPIC spec goes into some detail about exit codes from
validateRequest() and the subsequent behavior of the container
in terms of returning errors vs. proceeding to invoke the
servlet, codes that indicate success but a requirement to
continue dialog with the client before invoking the servlet,
etc. What should HAMs do? Should we specify behavior that
matches SAMs? Different behavior?
4.0 General
- How does SecurityContext determine the caller principal and
query the roles? Is it the responsibility of containers to
ensure the SecurityContext is populated with the correct
information? Does it get the current Subject of the stack and
use that to get the CallerPrincipal and test roles? Etc.
4.2 Relationship to other specs
- This spec declares that the new security context supercedes
all these other mechanisms. Should we say something about what
the legacy behavior is, for older apps, and the extent to which
the old and new mechanisms must return the same values? I.e.,
we could declare that the older mechanisms remain, for legacy
support, but must be implemented by delegating to the new
SecurityContext, or, at minimum, behave at all times as if they
delegated to SecurityContext. (This also implies that the new
SecurityContext must return values consistent with the older
APIs.)
4.3 Testing for Caller Data
- Downcasting -- to be clear, this section does not assume that
HAM and SAM are the only possible sources of Caller Principals,
correct? I.e., a container might choose to implement BASIC,
FORM, and CERT using proprietary interfaces. Or are we
suggesting that all containers should provide BASIC/FORM/CERT
via HAM or SAM?
- isCallerInRole() -- this should not be defined to map
explicitly to a group principal in the subject; rather, it
should map to a role in a security constraint, which may be
mapped arbitrarily by the container. See, e.g., the javadoc for
isCallerInRole/isUserInRole for EJBContext/HttpServletRequest.
--
Will Hopkins | Platform Security Architect | +1.781.442.0310
Oracle Cloud Application Foundation
35 Network Drive, Burlington, MA 01803