Search in sources :

Example 1 with SignatureSignerContext

use of org.keycloak.crypto.SignatureSignerContext in project keycloak by keycloak.

the class UserInfoEndpoint method issueUserInfo.

private Response issueUserInfo(String tokenString) {
    cors = Cors.add(request).auth().allowedMethods(request.getHttpMethod()).auth().exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS);
    try {
        session.clientPolicy().triggerOnEvent(new UserInfoRequestContext(tokenString));
    } catch (ClientPolicyException cpe) {
        throw new CorsErrorResponseException(cors.allowAllOrigins(), cpe.getError(), cpe.getErrorDetail(), cpe.getErrorStatus());
    }
    EventBuilder event = new EventBuilder(realm, session, clientConnection).event(EventType.USER_INFO_REQUEST).detail(Details.AUTH_METHOD, Details.VALIDATE_ACCESS_TOKEN);
    if (tokenString == null) {
        event.error(Errors.INVALID_TOKEN);
        throw new CorsErrorResponseException(cors.allowAllOrigins(), OAuthErrorException.INVALID_REQUEST, "Token not provided", Response.Status.BAD_REQUEST);
    }
    AccessToken token;
    ClientModel clientModel = null;
    try {
        TokenVerifier<AccessToken> verifier = TokenVerifier.create(tokenString, AccessToken.class).withDefaultChecks().realmUrl(Urls.realmIssuer(session.getContext().getUri().getBaseUri(), realm.getName()));
        SignatureVerifierContext verifierContext = session.getProvider(SignatureProvider.class, verifier.getHeader().getAlgorithm().name()).verifier(verifier.getHeader().getKeyId());
        verifier.verifierContext(verifierContext);
        token = verifier.verify().getToken();
        clientModel = realm.getClientByClientId(token.getIssuedFor());
        if (clientModel == null) {
            event.error(Errors.CLIENT_NOT_FOUND);
            throw new CorsErrorResponseException(cors.allowAllOrigins(), OAuthErrorException.INVALID_REQUEST, "Client not found", Response.Status.BAD_REQUEST);
        }
        cors.allowedOrigins(session, clientModel);
        TokenVerifier.createWithoutSignature(token).withChecks(NotBeforeCheck.forModel(clientModel), new TokenManager.TokenRevocationCheck(session)).verify();
    } catch (VerificationException e) {
        if (clientModel == null) {
            cors.allowAllOrigins();
        }
        event.error(Errors.INVALID_TOKEN);
        throw newUnauthorizedErrorResponseException(OAuthErrorException.INVALID_TOKEN, "Token verification failed");
    }
    if (!clientModel.getProtocol().equals(OIDCLoginProtocol.LOGIN_PROTOCOL)) {
        event.error(Errors.INVALID_CLIENT);
        throw new CorsErrorResponseException(cors, Errors.INVALID_CLIENT, "Wrong client protocol.", Response.Status.BAD_REQUEST);
    }
    session.getContext().setClient(clientModel);
    event.client(clientModel);
    if (!clientModel.isEnabled()) {
        event.error(Errors.CLIENT_DISABLED);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "Client disabled", Response.Status.BAD_REQUEST);
    }
    UserSessionModel userSession = findValidSession(token, event, clientModel);
    UserModel userModel = userSession.getUser();
    if (userModel == null) {
        event.error(Errors.USER_NOT_FOUND);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "User not found", Response.Status.BAD_REQUEST);
    }
    event.user(userModel).detail(Details.USERNAME, userModel.getUsername());
    // https://tools.ietf.org/html/draft-ietf-oauth-mtls-08#section-3
    if (OIDCAdvancedConfigWrapper.fromClientModel(clientModel).isUseMtlsHokToken()) {
        if (!MtlsHoKTokenUtil.verifyTokenBindingWithClientCertificate(token, request, session)) {
            event.error(Errors.NOT_ALLOWED);
            throw newUnauthorizedErrorResponseException(OAuthErrorException.UNAUTHORIZED_CLIENT, "Client certificate missing, or its thumbprint and one in the refresh token did NOT match");
        }
    }
    // Existence of authenticatedClientSession for our client already handled before
    AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(clientModel.getId());
    // Retrieve by latest scope parameter
    ClientSessionContext clientSessionCtx = DefaultClientSessionContext.fromClientSessionScopeParameter(clientSession, session);
    AccessToken userInfo = new AccessToken();
    tokenManager.transformUserInfoAccessToken(session, userInfo, userSession, clientSessionCtx);
    Map<String, Object> claims = tokenManager.generateUserInfoClaims(userInfo, userModel);
    Response.ResponseBuilder responseBuilder;
    OIDCAdvancedConfigWrapper cfg = OIDCAdvancedConfigWrapper.fromClientModel(clientModel);
    if (cfg.isUserInfoSignatureRequired()) {
        String issuerUrl = Urls.realmIssuer(session.getContext().getUri().getBaseUri(), realm.getName());
        String audience = clientModel.getClientId();
        claims.put("iss", issuerUrl);
        claims.put("aud", audience);
        String signatureAlgorithm = session.tokens().signatureAlgorithm(TokenCategory.USERINFO);
        SignatureProvider signatureProvider = session.getProvider(SignatureProvider.class, signatureAlgorithm);
        SignatureSignerContext signer = signatureProvider.signer();
        String signedUserInfo = new JWSBuilder().type("JWT").jsonContent(claims).sign(signer);
        responseBuilder = Response.ok(signedUserInfo).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JWT);
        event.detail(Details.SIGNATURE_REQUIRED, "true");
        event.detail(Details.SIGNATURE_ALGORITHM, cfg.getUserInfoSignedResponseAlg().toString());
    } else {
        responseBuilder = Response.ok(claims).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
        event.detail(Details.SIGNATURE_REQUIRED, "false");
    }
    event.success();
    return cors.builder(responseBuilder).build();
}
Also used : UserSessionModel(org.keycloak.models.UserSessionModel) SignatureVerifierContext(org.keycloak.crypto.SignatureVerifierContext) OIDCAdvancedConfigWrapper(org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper) SignatureSignerContext(org.keycloak.crypto.SignatureSignerContext) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) ClientPolicyException(org.keycloak.services.clientpolicy.ClientPolicyException) JWSBuilder(org.keycloak.jose.jws.JWSBuilder) UserModel(org.keycloak.models.UserModel) Response(javax.ws.rs.core.Response) HttpResponse(org.jboss.resteasy.spi.HttpResponse) ClientModel(org.keycloak.models.ClientModel) SignatureProvider(org.keycloak.crypto.SignatureProvider) UserInfoRequestContext(org.keycloak.services.clientpolicy.context.UserInfoRequestContext) EventBuilder(org.keycloak.events.EventBuilder) DefaultClientSessionContext(org.keycloak.services.util.DefaultClientSessionContext) ClientSessionContext(org.keycloak.models.ClientSessionContext) AccessToken(org.keycloak.representations.AccessToken) VerificationException(org.keycloak.common.VerificationException) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException)

Example 2 with SignatureSignerContext

use of org.keycloak.crypto.SignatureSignerContext in project keycloak by keycloak.

the class TestingOIDCEndpointsApplicationResource method setOidcRequest.

private void setOidcRequest(Object oidcRequest, String jwaAlgorithm, String clientSecret) {
    if (!isSupportedAlgorithm(jwaAlgorithm))
        throw new BadRequestException("Unknown argument: " + jwaAlgorithm);
    if ("none".equals(jwaAlgorithm)) {
        clientData.setOidcRequest(new JWSBuilder().jsonContent(oidcRequest).none());
    } else {
        SignatureSignerContext signer;
        switch(jwaAlgorithm) {
            case Algorithm.HS256:
            case Algorithm.HS384:
            case Algorithm.HS512:
                KeyWrapper keyWrapper = new KeyWrapper();
                SecretKey secretKey = new SecretKeySpec(clientSecret.getBytes(StandardCharsets.UTF_8), JavaAlgorithm.getJavaAlgorithm(jwaAlgorithm));
                keyWrapper.setSecretKey(secretKey);
                String kid = KeyUtils.createKeyId(secretKey);
                keyWrapper.setKid(kid);
                keyWrapper.setAlgorithm(jwaAlgorithm);
                keyWrapper.setUse(KeyUse.SIG);
                keyWrapper.setType(KeyType.OCT);
                signer = new MacSignatureSignerContext(keyWrapper);
                clientData.setOidcRequest(new JWSBuilder().kid(kid).jsonContent(oidcRequest).sign(signer));
                break;
            default:
                throw new BadRequestException("Unknown jwaAlgorithm: " + jwaAlgorithm);
        }
    }
}
Also used : KeyWrapper(org.keycloak.crypto.KeyWrapper) SecretKey(javax.crypto.SecretKey) ServerECDSASignatureSignerContext(org.keycloak.crypto.ServerECDSASignatureSignerContext) MacSignatureSignerContext(org.keycloak.crypto.MacSignatureSignerContext) AsymmetricSignatureSignerContext(org.keycloak.crypto.AsymmetricSignatureSignerContext) SignatureSignerContext(org.keycloak.crypto.SignatureSignerContext) SecretKeySpec(javax.crypto.spec.SecretKeySpec) BadRequestException(javax.ws.rs.BadRequestException) MacSignatureSignerContext(org.keycloak.crypto.MacSignatureSignerContext) JWSBuilder(org.keycloak.jose.jws.JWSBuilder)

Example 3 with SignatureSignerContext

use of org.keycloak.crypto.SignatureSignerContext in project keycloak by keycloak.

the class AbstractClientPoliciesTest method createSignedRequestToken.

// Signed JWT for client authentication utility
protected String createSignedRequestToken(String clientId, PrivateKey privateKey, PublicKey publicKey, String algorithm) {
    JsonWebToken jwt = createRequestToken(clientId, getRealmInfoUrl());
    String kid = KeyUtils.createKeyId(publicKey);
    SignatureSignerContext signer = oauth.createSigner(privateKey, kid, algorithm);
    return new JWSBuilder().kid(kid).jsonContent(jwt).sign(signer);
}
Also used : SignatureSignerContext(org.keycloak.crypto.SignatureSignerContext) JsonWebToken(org.keycloak.representations.JsonWebToken) JWSBuilder(org.keycloak.jose.jws.JWSBuilder)

Example 4 with SignatureSignerContext

use of org.keycloak.crypto.SignatureSignerContext in project keycloak by keycloak.

the class CIBAAuthenticationRequest method serialize.

/**
 * Serializes this instance to a JWE.
 *
 * @param session the session
 * @return the JWE
 */
public String serialize(KeycloakSession session) {
    try {
        SignatureProvider signatureProvider = session.getProvider(SignatureProvider.class, Algorithm.HS256);
        SignatureSignerContext signer = signatureProvider.signer();
        String encodedJwt = new JWSBuilder().type("JWT").jsonContent(this).sign(signer);
        SecretKey aesKey = session.keys().getActiveKey(session.getContext().getRealm(), KeyUse.ENC, Algorithm.AES).getSecretKey();
        SecretKey hmacKey = session.keys().getActiveKey(session.getContext().getRealm(), KeyUse.SIG, Algorithm.HS256).getSecretKey();
        return TokenUtil.jweDirectEncode(aesKey, hmacKey, encodedJwt.getBytes("UTF-8"));
    } catch (JWEException | UnsupportedEncodingException e) {
        throw new RuntimeException("Error encoding auth_req_id.", e);
    }
}
Also used : SignatureProvider(org.keycloak.crypto.SignatureProvider) SecretKey(javax.crypto.SecretKey) SignatureSignerContext(org.keycloak.crypto.SignatureSignerContext) JWEException(org.keycloak.jose.jwe.JWEException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) JWSBuilder(org.keycloak.jose.jws.JWSBuilder)

Example 5 with SignatureSignerContext

use of org.keycloak.crypto.SignatureSignerContext in project keycloak by keycloak.

the class ClientRegistrationTokenUtils method updateTokenSignature.

public static String updateTokenSignature(KeycloakSession session, ClientRegistrationAuth auth) {
    String algorithm = session.tokens().signatureAlgorithm(TokenCategory.INTERNAL);
    SignatureSignerContext signer = session.getProvider(SignatureProvider.class, algorithm).signer();
    if (signer.getKid().equals(auth.getKid())) {
        return auth.getToken();
    } else {
        RegistrationAccessToken regToken = new RegistrationAccessToken();
        regToken.setRegistrationAuth(auth.getRegistrationAuth().toString().toLowerCase());
        regToken.type(auth.getJwt().getType());
        regToken.id(auth.getJwt().getId());
        regToken.issuedAt(Time.currentTime());
        regToken.expiration(0);
        regToken.issuer(auth.getJwt().getIssuer());
        regToken.audience(auth.getJwt().getIssuer());
        String token = new JWSBuilder().jsonContent(regToken).sign(signer);
        return token;
    }
}
Also used : SignatureProvider(org.keycloak.crypto.SignatureProvider) SignatureSignerContext(org.keycloak.crypto.SignatureSignerContext) JWSBuilder(org.keycloak.jose.jws.JWSBuilder)

Aggregations

SignatureSignerContext (org.keycloak.crypto.SignatureSignerContext)8 JWSBuilder (org.keycloak.jose.jws.JWSBuilder)6 SignatureProvider (org.keycloak.crypto.SignatureProvider)4 SecretKey (javax.crypto.SecretKey)2 AsymmetricSignatureSignerContext (org.keycloak.crypto.AsymmetricSignatureSignerContext)2 KeyWrapper (org.keycloak.crypto.KeyWrapper)2 ServerECDSASignatureSignerContext (org.keycloak.crypto.ServerECDSASignatureSignerContext)2 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 SecretKeySpec (javax.crypto.spec.SecretKeySpec)1 BadRequestException (javax.ws.rs.BadRequestException)1 Response (javax.ws.rs.core.Response)1 HttpResponse (org.jboss.resteasy.spi.HttpResponse)1 VerificationException (org.keycloak.common.VerificationException)1 MacSignatureSignerContext (org.keycloak.crypto.MacSignatureSignerContext)1 SignatureVerifierContext (org.keycloak.crypto.SignatureVerifierContext)1 EventBuilder (org.keycloak.events.EventBuilder)1 JWEException (org.keycloak.jose.jwe.JWEException)1 AuthenticatedClientSessionModel (org.keycloak.models.AuthenticatedClientSessionModel)1 ClientModel (org.keycloak.models.ClientModel)1 ClientSessionContext (org.keycloak.models.ClientSessionContext)1