use of org.keycloak.common.VerificationException in project keycloak by keycloak.
the class KeyPairVerifier method verify.
public static void verify(String privateKeyPem, String publicKeyPem) throws VerificationException {
PrivateKey privateKey;
try {
privateKey = PemUtils.decodePrivateKey(privateKeyPem);
} catch (Exception e) {
throw new VerificationException("Failed to decode private key");
}
PublicKey publicKey;
try {
publicKey = PemUtils.decodePublicKey(publicKeyPem);
} catch (Exception e) {
throw new VerificationException("Failed to decode public key");
}
try {
String jws = new JWSBuilder().content("content".getBytes()).rsa256(privateKey);
if (!RSAProvider.verify(new JWSInput(jws), publicKey)) {
throw new VerificationException("Keys don't match");
}
} catch (Exception e) {
throw new VerificationException("Keys don't match");
}
}
use of org.keycloak.common.VerificationException in project keycloak by keycloak.
the class AsymmetricSignatureVerifierContext method verify.
@Override
public boolean verify(byte[] data, byte[] signature) throws VerificationException {
try {
Signature verifier = Signature.getInstance(JavaAlgorithm.getJavaAlgorithm(key.getAlgorithmOrDefault()));
verifier.initVerify((PublicKey) key.getPublicKey());
verifier.update(data);
return verifier.verify(signature);
} catch (Exception e) {
throw new VerificationException("Signing failed", e);
}
}
use of org.keycloak.common.VerificationException in project keycloak by keycloak.
the class TokenManager method validateToken.
public TokenValidation validateToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, RefreshToken oldToken, HttpHeaders headers) throws OAuthErrorException {
UserSessionModel userSession = null;
boolean offline = TokenUtil.TOKEN_TYPE_OFFLINE.equals(oldToken.getType());
if (offline) {
UserSessionManager sessionManager = new UserSessionManager(session);
userSession = sessionManager.findOfflineUserSession(realm, oldToken.getSessionState());
if (userSession != null) {
// Revoke timeouted offline userSession
if (!AuthenticationManager.isOfflineSessionValid(realm, userSession)) {
sessionManager.revokeOfflineUserSession(userSession);
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline session not active", "Offline session not active");
}
} else {
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline user session not found", "Offline user session not found");
}
} else {
// Find userSession regularly for online tokens
userSession = session.sessions().getUserSession(realm, oldToken.getSessionState());
if (!AuthenticationManager.isSessionValid(realm, userSession)) {
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, connection, headers, true);
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session not active", "Session not active");
}
}
UserModel user = userSession.getUser();
if (user == null) {
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token", "Unknown user");
}
if (!user.isEnabled()) {
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "User disabled", "User disabled");
}
if (oldToken.isIssuedBeforeSessionStart(userSession.getStarted())) {
logger.debug("Refresh toked issued before the user session started");
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Refresh toked issued before the user session started");
}
ClientModel client = session.getContext().getClient();
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
// Can theoretically happen in cross-dc environment. Try to see if userSession with our client is available in remoteCache
if (clientSession == null) {
userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, userSession.getId(), offline, client.getId());
if (userSession != null) {
clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
} else {
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session doesn't have required client", "Session doesn't have required client");
}
}
if (oldToken.isIssuedBeforeSessionStart(clientSession.getStarted())) {
logger.debug("Refresh toked issued before the client session started");
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Refresh toked issued before the client session started");
}
if (!client.getClientId().equals(oldToken.getIssuedFor())) {
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Unmatching clients", "Unmatching clients");
}
try {
TokenVerifier.createWithoutSignature(oldToken).withChecks(NotBeforeCheck.forModel(client), NotBeforeCheck.forModel(session, realm, user)).verify();
} catch (VerificationException e) {
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token");
}
// Setup clientScopes from refresh token to the context
String oldTokenScope = oldToken.getScope();
// Case when offline token is migrated from previous version
if (oldTokenScope == null && userSession.isOffline()) {
logger.debugf("Migrating offline token of user '%s' for client '%s' of realm '%s'", user.getUsername(), client.getClientId(), realm.getName());
MigrationUtils.migrateOldOfflineToken(session, realm, client, user);
oldTokenScope = OAuth2Constants.OFFLINE_ACCESS;
}
ClientSessionContext clientSessionCtx = DefaultClientSessionContext.fromClientSessionAndScopeParameter(clientSession, oldTokenScope, session);
// Check user didn't revoke granted consent
if (!verifyConsentStillAvailable(session, user, client, clientSessionCtx.getClientScopesStream())) {
throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "Client no longer has requested consent from user");
}
clientSessionCtx.setAttribute(OIDCLoginProtocol.NONCE_PARAM, oldToken.getNonce());
// recreate token.
AccessToken newToken = createClientAccessToken(session, realm, client, user, userSession, clientSessionCtx);
return new TokenValidation(user, userSession, clientSessionCtx, newToken);
}
use of org.keycloak.common.VerificationException in project keycloak by keycloak.
the class OAuthClient method verifyToken.
public <T extends JsonWebToken> T verifyToken(String token, Class<T> clazz) {
try {
TokenVerifier<T> verifier = TokenVerifier.create(token, clazz);
String kid = verifier.getHeader().getKeyId();
String algorithm = verifier.getHeader().getAlgorithm().name();
KeyWrapper key = getRealmPublicKey(realm, algorithm, kid);
AsymmetricSignatureVerifierContext verifierContext;
switch(algorithm) {
case Algorithm.ES256:
case Algorithm.ES384:
case Algorithm.ES512:
verifierContext = new ServerECDSASignatureVerifierContext(key);
break;
default:
verifierContext = new AsymmetricSignatureVerifierContext(key);
}
verifier.verifierContext(verifierContext);
verifier.verify();
return verifier.getToken();
} catch (VerificationException e) {
throw new RuntimeException("Failed to decode token", e);
}
}
use of org.keycloak.common.VerificationException in project keycloak by keycloak.
the class LoginActionsService method handleActionToken.
protected <T extends JsonWebToken & ActionTokenKeyModel> Response handleActionToken(String tokenString, String execution, String clientId, String tabId) {
T token;
ActionTokenHandler<T> handler;
ActionTokenContext<T> tokenContext;
String eventError = null;
String defaultErrorMessage = null;
AuthenticationSessionModel authSession = null;
// Setup client, so error page will contain "back to application" link
ClientModel client = null;
if (clientId != null) {
client = realm.getClientByClientId(clientId);
}
AuthenticationSessionManager authenticationSessionManager = new AuthenticationSessionManager(session);
if (client != null) {
session.getContext().setClient(client);
authSession = authenticationSessionManager.getCurrentAuthenticationSession(realm, client, tabId);
}
event.event(EventType.EXECUTE_ACTION_TOKEN);
// First resolve action token handler
try {
if (tokenString == null) {
throw new ExplainedTokenVerificationException(null, Errors.NOT_ALLOWED, Messages.INVALID_REQUEST);
}
TokenVerifier<DefaultActionTokenKey> tokenVerifier = TokenVerifier.create(tokenString, DefaultActionTokenKey.class);
DefaultActionTokenKey aToken = tokenVerifier.getToken();
event.detail(Details.TOKEN_ID, aToken.getId()).detail(Details.ACTION, aToken.getActionId()).user(aToken.getUserId());
handler = resolveActionTokenHandler(aToken.getActionId());
eventError = handler.getDefaultEventError();
defaultErrorMessage = handler.getDefaultErrorMessage();
if (!realm.isEnabled()) {
throw new ExplainedTokenVerificationException(aToken, Errors.REALM_DISABLED, Messages.REALM_NOT_ENABLED);
}
if (!checkSsl()) {
throw new ExplainedTokenVerificationException(aToken, Errors.SSL_REQUIRED, Messages.HTTPS_REQUIRED);
}
TokenVerifier<DefaultActionTokenKey> verifier = tokenVerifier.withChecks(// Token introspection checks
TokenVerifier.IS_ACTIVE, new TokenVerifier.RealmUrlCheck(Urls.realmIssuer(session.getContext().getUri().getBaseUri(), realm.getName())), ACTION_TOKEN_BASIC_CHECKS);
String kid = verifier.getHeader().getKeyId();
String algorithm = verifier.getHeader().getAlgorithm().name();
SignatureVerifierContext signatureVerifier = session.getProvider(SignatureProvider.class, algorithm).verifier(kid);
verifier.verifierContext(signatureVerifier);
verifier.verify();
token = TokenVerifier.create(tokenString, handler.getTokenClass()).getToken();
} catch (TokenNotActiveException ex) {
if (authSession != null) {
event.clone().error(Errors.EXPIRED_CODE);
String flowPath = authSession.getClientNote(AuthorizationEndpointBase.APP_INITIATED_FLOW);
if (flowPath == null) {
flowPath = AUTHENTICATE_PATH;
}
AuthenticationProcessor.resetFlow(authSession, flowPath);
// Process correct flow
return processFlowFromPath(flowPath, authSession, Messages.EXPIRED_ACTION_TOKEN_SESSION_EXISTS);
}
return handleActionTokenVerificationException(null, ex, Errors.EXPIRED_CODE, Messages.EXPIRED_ACTION_TOKEN_NO_SESSION);
} catch (ExplainedTokenVerificationException ex) {
return handleActionTokenVerificationException(null, ex, ex.getErrorEvent(), ex.getMessage());
} catch (ExplainedVerificationException ex) {
return handleActionTokenVerificationException(null, ex, ex.getErrorEvent(), ex.getMessage());
} catch (VerificationException ex) {
return handleActionTokenVerificationException(null, ex, eventError, defaultErrorMessage);
}
// Now proceed with the verification and handle the token
tokenContext = new ActionTokenContext(session, realm, session.getContext().getUri(), clientConnection, request, event, handler, execution, this::processFlow, this::brokerLoginFlow);
try {
String tokenAuthSessionCompoundId = handler.getAuthenticationSessionIdFromToken(token, tokenContext, authSession);
if (tokenAuthSessionCompoundId != null) {
// This can happen if the token contains ID but user opens the link in a new browser
String sessionId = AuthenticationSessionCompoundId.encoded(tokenAuthSessionCompoundId).getRootSessionId();
LoginActionsServiceChecks.checkNotLoggedInYet(tokenContext, authSession, sessionId);
}
if (authSession == null) {
authSession = handler.startFreshAuthenticationSession(token, tokenContext);
tokenContext.setAuthenticationSession(authSession, true);
} else if (tokenAuthSessionCompoundId == null || !LoginActionsServiceChecks.doesAuthenticationSessionFromCookieMatchOneFromToken(tokenContext, authSession, tokenAuthSessionCompoundId)) {
// There exists an authentication session but no auth session ID was received in the action token
logger.debugf("Authentication session in progress but no authentication session ID was found in action token %s, restarting.", token.getId());
authenticationSessionManager.removeAuthenticationSession(realm, authSession, false);
authSession = handler.startFreshAuthenticationSession(token, tokenContext);
tokenContext.setAuthenticationSession(authSession, true);
processLocaleParam(authSession);
}
initLoginEvent(authSession);
event.event(handler.eventType());
LoginActionsServiceChecks.checkIsUserValid(token, tokenContext);
LoginActionsServiceChecks.checkIsClientValid(token, tokenContext);
session.getContext().setClient(authSession.getClient());
TokenVerifier.createWithoutSignature(token).withChecks(handler.getVerifiers(tokenContext)).verify();
authSession = tokenContext.getAuthenticationSession();
event = tokenContext.getEvent();
event.event(handler.eventType());
if (!handler.canUseTokenRepeatedly(token, tokenContext)) {
LoginActionsServiceChecks.checkTokenWasNotUsedYet(token, tokenContext);
authSession.setAuthNote(AuthenticationManager.INVALIDATE_ACTION_TOKEN, token.serializeKey());
}
authSession.setAuthNote(DefaultActionTokenKey.ACTION_TOKEN_USER_ID, token.getUserId());
authSession.setAuthNote(Constants.KEY, tokenString);
return handler.handleToken(token, tokenContext);
} catch (ExplainedTokenVerificationException ex) {
return handleActionTokenVerificationException(tokenContext, ex, ex.getErrorEvent(), ex.getMessage());
} catch (LoginActionsServiceException ex) {
Response response = ex.getResponse();
return response == null ? handleActionTokenVerificationException(tokenContext, ex, eventError, defaultErrorMessage) : response;
} catch (VerificationException ex) {
return handleActionTokenVerificationException(tokenContext, ex, eventError, defaultErrorMessage);
}
}
Aggregations