jakartaee/security

Add authentication mechanism for JWT

hantsy opened this issue ยท 12 comments

Combine the effort of Microprofile JWT, and provides a standard JWT authentication mechanism for Http, WebSocket.

Mainly used in a ResoruceServer oauth2 role, provides one of the following config to decode JWT.

  • issuerUri
  • jwksUri
  • publicKey location or value

This was in scope for Jakarta Security 3.0, but we didn't had time to look at this. Note that quite a few servers do actually implement MicroProfile JWT using Jakarta Security. See e.g. https://github.com/omnifaces/jwt

I brought up this topic a couple of times, but despite EE & MP alignments, it's still not 100% clear how to go about doing this. There is a vague notion about this in the MP specs already, but I personally feel it's not clear enough.

I would like some wording such as the following in the MP JWT spec:

"In a Jakarta EE environment, the runtime MUST make the JWT functionality available via an HTTPAuthenticationMechanism, and it MUST use the LoginConfig annotation to make this HTTPAuthenticationMechanism available as an enabled CDI bean"

From the reverse side, I'm not yet sure what wording or process to use for EE to "import" the actual MP JWT spec.

I would like use the OAuth 2 role name to define the spec, it is easy to apply them in different scenes. For example.

  • OAuth2Client or OidcClient, support OAuth 2.1 spec, support basic authorization code, client credentials, device code flow, (ignore resource owner password and implicit flow which are not recommended due to security issues). This mechanism is used in a general web application(eg. Faces, MVC, Servlet), gateway application or API client in an application( manually use client credentials to communicate with other APIs).
  • ResourceServer, supports both JwtToken and OpaqueToken, mainly used in a backend API application to protect APIs.
  • AuthenticationServer, for Jakarta EE specs, we do not need to implement an AuthenticationServer role, the existing IDP providers fill the blank.

We should start the discussion and some prototyping of this soon. But as mentioned, if we want/need to directly import the MP spec into EE we probably have to do some cross platform discussion between EE and MP.

So, the JWT authentication mechanism would simply validate a json web token, did I get it correctly ?

Like the OpenIdAuthenticationDefinition without the redirect behaviour ?

keilw commented

@arjantijms The above discussion already happens, but the question is, would we need anything JWT specific HERE (in the Security Spec / API) or would Soteria be suffient?
There something along the lines of omni-jwt sounds reasonable and there is no big issue to use e.g. Microprofile-JWT while using the MP API here bares the risk of cyclic dependencies which must be avoided.

@keilw I believe a @JWTAuthenticationMechanismDefinition would be a good addition to the spec, independently from the already working implementations based on the current API.

Similarly to the OpenIdAuthenticationDefinition, it should also have a property for extracting the principal name from the decoded jwt.

keilw commented

@amoscatelli If we added an annotation like that it would make using MP JWT especially for its @Claim annotation pretty useless. The Claims enumeration has a very similar purpose to the OpenIdConstant collection here, so we could have something along the lines of JwtConstant or similar. With that only the actual JWT would be missing, which could either be done in the implementation or by using the CallerPrincipal because MP JWT's JsonWebToken is merely an extension to the standard JDK Principal as well.

I am little confused about the annotation naming of OpenIdAuthenticationDefinition, OpenId is an old protocol and deprecated now, OpenIdConnect is the exact feature defined in OpenIdAuthenticationDefinition.

I would like add the OAuth2 role to recognize this annotation naming.

  • OAuth2ClientAuthenticationDefinition(support both OpenIdConnect and the raw OAuth 2.1)
  • OAuth2ResourceServerAuthenticationDefinition(support both JWT and Opaque Token introspection )

@amoscatelli If we added an annotation like that it would make using MP JWT especially for its @Claim annotation pretty useless. The Claims enumeration has a very similar purpose to the OpenIdConstant collection here, so we could have something along the lines of JwtConstant or similar. With that only the actual JWT would be missing, which could either be done in the implementation or by using the CallerPrincipal because MP JWT's JsonWebToken is merely an extension to the standard JDK Principal as well.

Thank you, I missed MP JWT.

Does MP JWT work for Servlet/SOAP/WebSocket too ?

It seems so, it should provide an authentication mechanism ! good to know

I would like move MP JWT to Jakarta Security, and refactor it with Jakarta Security APIs, and deprecated MP JWT at the same time.

And in the existing MP JWT, I do not think upn and groups is required.

  • sub is a good placement of upn.

  • Use a custom claimsDefinition = @ClaimsDefinition(callerGroupsClaim = "http://www.jakarta.ee/roles")(existed in the OpenIDConnect authentication) to map custom claims to groups directly.

  • Additionally I hope provide an alternative converter bean @ClaimsDefinition(callerGroupsClaimConverter = "${myConverter}") to convert claims to security context groups.

    @ApplicationScope
    @Named("myConverter")
    class MyConverter implements Converter<Claims, Set<String>>{
        public Set<String> convert(Claims claims){
            // Jakarta Security apply the converters and 
            // set groups to the current pricipal
        }  
    }