use of org.keycloak.crypto.SignatureProvider 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();
}
use of org.keycloak.crypto.SignatureProvider in project keycloak by keycloak.
the class DefaultTokenManager method decode.
@Override
public <T extends Token> T decode(String token, Class<T> clazz) {
if (token == null) {
return null;
}
try {
JWSInput jws = new JWSInput(token);
String signatureAlgorithm = jws.getHeader().getAlgorithm().name();
SignatureProvider signatureProvider = session.getProvider(SignatureProvider.class, signatureAlgorithm);
if (signatureProvider == null) {
return null;
}
String kid = jws.getHeader().getKeyId();
// Backwards compatibility. Old offline tokens and cookies didn't have KID in the header
if (kid == null) {
logger.debugf("KID is null in token. Using the realm active key to verify token signature.");
kid = session.keys().getActiveKey(session.getContext().getRealm(), KeyUse.SIG, signatureAlgorithm).getKid();
}
boolean valid = signatureProvider.verifier(kid).verify(jws.getEncodedSignatureInput().getBytes("UTF-8"), jws.getSignature());
return valid ? jws.readJsonContent(clazz) : null;
} catch (Exception e) {
logger.debug("Failed to decode token", e);
return null;
}
}
use of org.keycloak.crypto.SignatureProvider in project keycloak by keycloak.
the class DefaultTokenManager method encode.
@Override
public String encode(Token token) {
String signatureAlgorithm = signatureAlgorithm(token.getCategory());
SignatureProvider signatureProvider = session.getProvider(SignatureProvider.class, signatureAlgorithm);
SignatureSignerContext signer = signatureProvider.signer();
String encodedToken = new JWSBuilder().type("JWT").jsonContent(token).sign(signer);
return encodedToken;
}
use of org.keycloak.crypto.SignatureProvider 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);
}
}
Aggregations