1515 * limitations under the License.
1616 */
1717
18- package org .keycloak .protocol .oidc .grants ;
18+ package org .keycloak .protocol .oidc .grants . jwtauthorization ;
1919
2020import jakarta .ws .rs .core .Response ;
2121
2222import org .keycloak .OAuth2Constants ;
2323import org .keycloak .OAuthErrorException ;
24+ import org .keycloak .authentication .authenticators .client .ClientAssertionState ;
2425import org .keycloak .broker .provider .BrokeredIdentityContext ;
2526import org .keycloak .broker .provider .JWTAuthorizationGrantProvider ;
2627import org .keycloak .cache .AlternativeLookupProvider ;
2728import org .keycloak .events .Details ;
2829import org .keycloak .events .Errors ;
2930import org .keycloak .events .EventType ;
31+ import org .keycloak .jose .jws .JWSInput ;
32+ import org .keycloak .jose .jws .JWSInputException ;
3033import org .keycloak .models .ClientModel ;
3134import org .keycloak .models .ClientSessionContext ;
3235import org .keycloak .models .FederatedIdentityModel ;
3336import org .keycloak .models .IdentityProviderModel ;
37+ import org .keycloak .models .KeycloakSession ;
3438import org .keycloak .models .UserModel ;
3539import org .keycloak .models .UserSessionModel ;
40+ import org .keycloak .protocol .oidc .JWTAuthorizationGrantValidator ;
3641import org .keycloak .protocol .oidc .OIDCAdvancedConfigWrapper ;
3742import org .keycloak .protocol .oidc .OIDCLoginProtocol ;
3843import org .keycloak .protocol .oidc .TokenManager ;
44+ import org .keycloak .protocol .oidc .grants .OAuth2GrantTypeBase ;
45+ import org .keycloak .protocol .oidc .grants .jwtauthorization .validator .DefaultJWTAuthorizationGrantValidator ;
46+ import org .keycloak .protocol .oidc .grants .jwtauthorization .validator .JWTAuthorizationGrantValidatorBase ;
47+ import org .keycloak .representations .JsonWebToken ;
3948import org .keycloak .services .CorsErrorResponseException ;
4049import org .keycloak .services .Urls ;
4150import org .keycloak .services .clientpolicy .ClientPolicyException ;
@@ -56,8 +65,38 @@ public Response process(Context context) {
5665
5766 try {
5867
59- JWTAuthorizationGrantValidator authorizationGrantContext = JWTAuthorizationGrantValidator .createValidator (
68+ if (assertion == null ) {
69+ throw new IllegalArgumentException ("Missing parameter:" + OAuth2Constants .ASSERTION );
70+ }
71+
72+ JWSInput jws ;
73+ try {
74+ jws = new JWSInput (assertion );
75+ } catch (JWSInputException e ) {
76+ throw new RuntimeException ("The provided assertion is not a valid JWT" );
77+ }
78+
79+ String jwtTokenType = jws .getHeader ().getType ();
80+ JWTAuthorizationGrantValidatorBase authorizationGrantContext =
81+ (JWTAuthorizationGrantValidatorBase ) session .getProvider (JWTAuthorizationGrantValidator .class , jwtTokenType );
82+ if ( authorizationGrantContext == null ){
83+ authorizationGrantContext = createDefaultValidator (
6084 context .getSession (), client , assertion , formParams .getFirst (OAuth2Constants .SCOPE ));
85+ } else {
86+ JsonWebToken jwt ;
87+ try {
88+ jwt = jws .readJsonContent (JsonWebToken .class );
89+ } catch (JWSInputException e ) {
90+ throw new RuntimeException ("The provided assertion is not a valid JWT" );
91+ }
92+
93+ ClientAssertionState clientAssertionState = new ClientAssertionState (OAuth2Constants .JWT_AUTHORIZATION_GRANT , assertion , jws , jwt );
94+ clientAssertionState .setClient (client );
95+
96+ authorizationGrantContext .setClientAssertionState (clientAssertionState );
97+ authorizationGrantContext .setScopeParam (formParams .getFirst (OAuth2Constants .SCOPE ));
98+ }
99+
61100 event .detail (Details .IDENTITY_PROVIDER_ISSUER , authorizationGrantContext .getIssuer ());
62101 event .detail (Details .IDENTITY_PROVIDER_USER_ID , authorizationGrantContext .getSubject ());
63102
@@ -166,6 +205,10 @@ protected AuthenticationSessionModel createSessionModel(RootAuthenticationSessio
166205 return authSession ;
167206 }
168207
208+ protected JWTAuthorizationGrantValidatorBase createDefaultValidator (KeycloakSession session , ClientModel client , String assertion , String scope ) {
209+ return DefaultJWTAuthorizationGrantValidator .createValidator (session , client , assertion , scope );
210+ }
211+
169212 @ Override
170213 protected boolean useRefreshToken () {
171214 return false ; // jwt auth grant never generates the refresh token
0 commit comments