[
https://issues.apache.org/jira/browse/JAMES-3522?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17307684#comment-17307684
]
Benoit Tellier commented on JAMES-3522:
---------------------------------------
https://jmap.io/server.html#401-unauthorized
```
As per the HTTP spec, the response MUST have a WWW-Authenticate header listing
the available authentication schemes.
```
I still believe this deserves more visibility...
Oups. Missed it.
> Allow authentication discovery on top of JMAP
> ---------------------------------------------
>
> Key: JAMES-3522
> URL: https://issues.apache.org/jira/browse/JAMES-3522
> Project: James Server
> Issue Type: New Feature
> Components: JMAP
> Reporter: Benoit Tellier
> Assignee: Antoine Duprat
> Priority: Major
> Time Spent: 10m
> Remaining Estimate: 0h
>
> Authentication discovery is a major interoperability concern on top of JMAP.
> As a third-party client, I have no prior knowledge of the authentication
> schemes supported by the JMAP server. As a client, I need a way to discover
> supported authentication scheme (to ease end user configuration options).
> Luckily, RFC-2617 (https://tools.ietf.org/html/rfc2617#section-3.2.1) about
> HTTP authentication introduce such a mechanism through `WWW-Authenticate`
> header. A failed 401 authentication would result in this header being
> positioned, allowing discovery for the client of the supported authentication
> mechanisms. The client can then set up the authentication mechanism it
> supports and prefer, without requiring user input.
> https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/WWW-Authenticate
> further
> RFC-7235 updates RFC-2617 (https://tools.ietf.org/html/rfc7235#section-4.1)
> {code:java}
> A server generating a 401 (Unauthorized) response MUST send a
> WWW-Authenticate header field containing at least one challenge.
> {code}
> So far James JMAP implementation only sends a 401 without setting
> WWW-Authenticate header field - and is thus not best practice compliant.
> We should infer the WWW-Authenticate from the AuthenticationStrategy James
> relies on. Ideally, the Authenticator class should aggregate supported
> challenges into a single header line. JMAP RFC-8620 endpoints should then add
> the WWW-Authenticate headers upon 401 errors.
> Here is an example of multi-challenge WWW-Authenticate header (RFC-7235):
> {code:java}
> WWW-Authenticate: Newauth realm="apps", type=1, title="Login to \"apps\"",
> Basic realm="simple"
> {code}
> Please note that this header also can be used, if desired, to give hints
> toward why auth failed... Example
> (https://tools.ietf.org/html/rfc6750#section-3):
> {code:java}
> HTTP/1.1 401 Unauthorized
> WWW-Authenticate: Bearer realm="example",
> error="invalid_token",
> error_description="The access token expired"
> {code}
> A full list of standard auth shemes is available here:
> http://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml
> Sadly, RFC-8620 do not mention the existence of RFC-7235 nor the existence of
> WWW-Authenticate header. I think we should start a thread about this topic
> within the IETF work-group. Maybe we should mandate "Basic" auth as a
> pre-requisite to ensure inter-operability. I propose myself to start this
> thread.
> h4. Proposed code changes
> As one might wish to customize authentication methods (eg: support OpenID
> connect or other custom auth mechanisms) we need to dynamicaly generate the
> WWW-Authenticate header for JMAP.
> First let's have a POJO representing an authentication challenge:
> {code:scala}
> trait AuthenticationScheme {
> val value: String
> }
> trait AuthenticationChallenge {
> val scheme: AuthenticationScheme
> val parameters: Map[String, String]
> }
> {code}
> Note that I propose to not strong type parameters (all defined in RFC-2617)
> for simplicity...
> Here is what basic authentication authentication challenge would look like:
> {code:scala}
> case object BasicAuthenticationScheme extends AuthenticationScheme {
> val value: String = "Basic"
> }
> case object BasicAuthenticationChallenge extends AuthenticationChallenge {
> val scheme: AuthenticationScheme = BasicAuthenticationScheme
> val parameters: Map[String, String] = Map("realm" -> "simple")
> }
> {code}
> Then we can advertise AuthenticationChallenges as part of
> AuthenticationStrategy:
> {code:java}
> public interface AuthenticationStrategy {
> // reminder: allow authentication
> Mono<MailboxSession> createMailboxSession(HttpServerRequest httpRequest);
> AuthenticationChallenges getChallenge();
> /* omitted as unrelevant here */
> }
> {code}
> All existing authentication strategies will need to be updated accordingly...
> Then the Authenticator class would aggregate AuthenticationChallenges into an
> AuthenticateHeader, attached to the UnauthorizedException (why => it allows
> authentication strategies to individually give hints on why auth failed, if
> desired...):
> {code:java}
> case class AuthenticateHeader(challenges: Seq[ AuthenticationChallenge]) {
> def headerValue: String = ???
> }
> case class UnauthorizedException(message: String, authenticateHeader:
> AuthenticateHeader) extends RuntimeException
> {code}
> We then can adapt all JMAPRoutes to position `WWW-Authenticate` header upon
> 401 - and adapt corresponding tests.
--
This message was sent by Atlassian Jira
(v8.3.4#803005)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]