protected AccessToken initToken( RealmModel realm, ClientModel client, UserModel user, UserSessionModel session, ClientSessionModel clientSession) { AccessToken token = new AccessToken(); if (clientSession != null) token.clientSession(clientSession.getId()); token.id(KeycloakModelUtils.generateId()); token.subject(user.getId()); token.audience(client.getClientId()); token.issuedNow(); token.issuedFor(client.getClientId()); token.issuer(clientSession.getNote(OIDCLoginProtocol.ISSUER)); if (session != null) { token.setSessionState(session.getId()); } if (realm.getAccessTokenLifespan() > 0) { token.expiration(Time.currentTime() + realm.getAccessTokenLifespan()); } Set<String> allowedOrigins = client.getWebOrigins(); if (allowedOrigins != null) { token.setAllowedOrigins(allowedOrigins); } return token; }
protected SAML2LogoutRequestBuilder createLogoutRequest( String logoutUrl, ClientSessionModel clientSession, ClientModel client) { // build userPrincipal with subject used at login SAML2LogoutRequestBuilder logoutBuilder = new SAML2LogoutRequestBuilder() .assertionExpiration(realm.getAccessCodeLifespan()) .issuer(getResponseIssuer(realm)) .sessionIndex(clientSession.getId()) .userPrincipal( clientSession.getNote(SAML_NAME_ID), clientSession.getNote(SAML_NAME_ID_FORMAT)) .destination(logoutUrl); return logoutBuilder; }
private void initEvent(ClientSessionModel clientSession) { event .event(EventType.LOGIN) .client(clientSession.getClient()) .user(clientSession.getUserSession().getUser()) .session(clientSession.getUserSession().getId()) .detail(Details.CODE_ID, clientSession.getId()) .detail(Details.REDIRECT_URI, clientSession.getRedirectUri()) .detail( Details.USERNAME, clientSession.getNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME)) .detail(Details.RESPONSE_TYPE, "code"); UserSessionModel userSession = clientSession.getUserSession(); if (userSession != null) { event.detail(Details.AUTH_METHOD, userSession.getAuthMethod()); event.detail(Details.USERNAME, userSession.getLoginUsername()); if (userSession.isRememberMe()) { event.detail(Details.REMEMBER_ME, "true"); } } }
public TokenValidation validateToken( KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, AccessToken oldToken, HttpHeaders headers) throws OAuthErrorException { UserModel user = session.users().getUserById(oldToken.getSubject(), realm); 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"); } UserSessionModel 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"); } ClientSessionModel clientSession = null; for (ClientSessionModel clientSessionModel : userSession.getClientSessions()) { if (clientSessionModel.getId().equals(oldToken.getClientSession())) { clientSession = clientSessionModel; break; } } if (clientSession == null) { throw new OAuthErrorException( OAuthErrorException.INVALID_GRANT, "Client session not active", "Client session not active"); } ClientModel client = clientSession.getClient(); if (!client.getClientId().equals(oldToken.getIssuedFor())) { throw new OAuthErrorException( OAuthErrorException.INVALID_GRANT, "Unmatching clients", "Unmatching clients"); } if (oldToken.getIssuedAt() < client.getNotBefore()) { throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token"); } if (oldToken.getIssuedAt() < realm.getNotBefore()) { throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token"); } // recreate token. Set<RoleModel> requestedRoles = TokenManager.getAccess(null, clientSession.getClient(), user); AccessToken newToken = createClientAccessToken( session, requestedRoles, realm, client, user, userSession, clientSession); verifyAccess(oldToken, newToken); return new TokenValidation(user, userSession, clientSession, newToken); }
@Override public Response authenticated(UserSessionModel userSession, ClientSessionCode accessCode) { ClientSessionModel clientSession = accessCode.getClientSession(); ClientModel client = clientSession.getClient(); SamlClient samlClient = new SamlClient(client); String requestID = clientSession.getNote(SAML_REQUEST_ID); String relayState = clientSession.getNote(GeneralConstants.RELAY_STATE); String redirectUri = clientSession.getRedirectUri(); String responseIssuer = getResponseIssuer(realm); String nameIdFormat = getNameIdFormat(samlClient, clientSession); String nameId = getNameId(nameIdFormat, clientSession, userSession); // save NAME_ID and format in clientSession as they may be persistent or transient or email and // not username // we'll need to send this back on a logout clientSession.setNote(SAML_NAME_ID, nameId); clientSession.setNote(SAML_NAME_ID_FORMAT, nameIdFormat); SAML2LoginResponseBuilder builder = new SAML2LoginResponseBuilder(); builder .requestID(requestID) .destination(redirectUri) .issuer(responseIssuer) .assertionExpiration(realm.getAccessCodeLifespan()) .subjectExpiration(realm.getAccessTokenLifespan()) .sessionIndex(clientSession.getId()) .requestIssuer(clientSession.getClient().getClientId()) .nameIdentifier(nameIdFormat, nameId) .authMethod(JBossSAMLURIConstants.AC_UNSPECIFIED.get()); if (!samlClient.includeAuthnStatement()) { builder.disableAuthnStatement(true); } List<ProtocolMapperProcessor<SAMLAttributeStatementMapper>> attributeStatementMappers = new LinkedList<>(); List<ProtocolMapperProcessor<SAMLLoginResponseMapper>> loginResponseMappers = new LinkedList<>(); ProtocolMapperProcessor<SAMLRoleListMapper> roleListMapper = null; Set<ProtocolMapperModel> mappings = accessCode.getRequestedProtocolMappers(); for (ProtocolMapperModel mapping : mappings) { ProtocolMapper mapper = (ProtocolMapper) session .getKeycloakSessionFactory() .getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper()); if (mapper == null) continue; if (mapper instanceof SAMLAttributeStatementMapper) { attributeStatementMappers.add( new ProtocolMapperProcessor<SAMLAttributeStatementMapper>( (SAMLAttributeStatementMapper) mapper, mapping)); } if (mapper instanceof SAMLLoginResponseMapper) { loginResponseMappers.add( new ProtocolMapperProcessor<SAMLLoginResponseMapper>( (SAMLLoginResponseMapper) mapper, mapping)); } if (mapper instanceof SAMLRoleListMapper) { roleListMapper = new ProtocolMapperProcessor<SAMLRoleListMapper>((SAMLRoleListMapper) mapper, mapping); } } Document samlDocument = null; try { ResponseType samlModel = builder.buildModel(); final AttributeStatementType attributeStatement = populateAttributeStatements( attributeStatementMappers, session, userSession, clientSession); populateRoles(roleListMapper, session, userSession, clientSession, attributeStatement); // SAML Spec 2.7.3 AttributeStatement must contain one or more Attribute or EncryptedAttribute if (attributeStatement.getAttributes().size() > 0) { AssertionType assertion = samlModel.getAssertions().get(0).getAssertion(); assertion.addStatement(attributeStatement); } samlModel = transformLoginResponse( loginResponseMappers, samlModel, session, userSession, clientSession); samlDocument = builder.buildDocument(samlModel); } catch (Exception e) { logger.error("failed", e); return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE); } JaxrsSAML2BindingBuilder bindingBuilder = new JaxrsSAML2BindingBuilder(); bindingBuilder.relayState(relayState); KeyManager keyManager = session.keys(); KeyManager.ActiveKey keys = keyManager.getActiveKey(realm); if (samlClient.requiresRealmSignature()) { String canonicalization = samlClient.getCanonicalizationMethod(); if (canonicalization != null) { bindingBuilder.canonicalizationMethod(canonicalization); } bindingBuilder .signatureAlgorithm(samlClient.getSignatureAlgorithm()) .signWith(keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate()) .signDocument(); } if (samlClient.requiresAssertionSignature()) { String canonicalization = samlClient.getCanonicalizationMethod(); if (canonicalization != null) { bindingBuilder.canonicalizationMethod(canonicalization); } bindingBuilder .signatureAlgorithm(samlClient.getSignatureAlgorithm()) .signWith(keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate()) .signAssertions(); } if (samlClient.requiresEncryption()) { PublicKey publicKey = null; try { publicKey = SamlProtocolUtils.getEncryptionValidationKey(client); } catch (Exception e) { logger.error("failed", e); return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE); } bindingBuilder.encrypt(publicKey); } try { return buildAuthenticatedResponse(clientSession, redirectUri, samlDocument, bindingBuilder); } catch (Exception e) { logger.error("failed", e); return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE); } }
/** * OAuth grant page. You should not invoked this directly! * * @param formData * @return */ @Path("consent") @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response processConsent(final MultivaluedMap<String, String> formData) { event.event(EventType.LOGIN).detail(Details.RESPONSE_TYPE, "code"); if (!checkSsl()) { return ErrorPage.error(session, Messages.HTTPS_REQUIRED); } String code = formData.getFirst("code"); ClientSessionCode accessCode = ClientSessionCode.parse(code, session, realm); if (accessCode == null || !accessCode.isValid(ClientSessionModel.Action.OAUTH_GRANT.name())) { event.error(Errors.INVALID_CODE); return ErrorPage.error(session, Messages.INVALID_ACCESS_CODE); } ClientSessionModel clientSession = accessCode.getClientSession(); event.detail(Details.CODE_ID, clientSession.getId()); String redirect = clientSession.getRedirectUri(); UserSessionModel userSession = clientSession.getUserSession(); UserModel user = userSession.getUser(); ClientModel client = clientSession.getClient(); event .client(client) .user(user) .detail(Details.RESPONSE_TYPE, "code") .detail(Details.REDIRECT_URI, redirect); event.detail(Details.AUTH_METHOD, userSession.getAuthMethod()); event.detail(Details.USERNAME, userSession.getLoginUsername()); if (userSession.isRememberMe()) { event.detail(Details.REMEMBER_ME, "true"); } if (!AuthenticationManager.isSessionValid(realm, userSession)) { AuthenticationManager.backchannelLogout( session, realm, userSession, uriInfo, clientConnection, headers, true); event.error(Errors.INVALID_CODE); return ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE); } event.session(userSession); if (formData.containsKey("cancel")) { LoginProtocol protocol = session.getProvider(LoginProtocol.class, clientSession.getAuthMethod()); protocol.setRealm(realm).setHttpHeaders(headers).setUriInfo(uriInfo); event.error(Errors.REJECTED_BY_USER); return protocol.consentDenied(clientSession); } UserConsentModel grantedConsent = user.getConsentByClient(client.getId()); if (grantedConsent == null) { grantedConsent = new UserConsentModel(client); user.addConsent(grantedConsent); } for (RoleModel role : accessCode.getRequestedRoles()) { grantedConsent.addGrantedRole(role); } for (ProtocolMapperModel protocolMapper : accessCode.getRequestedProtocolMappers()) { if (protocolMapper.isConsentRequired() && protocolMapper.getConsentText() != null) { grantedConsent.addGrantedProtocolMapper(protocolMapper); } } user.updateConsent(grantedConsent); event.detail(Details.CONSENT, Details.CONSENT_VALUE_CONSENT_GRANTED); event.success(); return authManager.redirectAfterSuccessfulFlow( session, realm, userSession, clientSession, request, uriInfo, clientConnection); }
public boolean verifyCode(String code) { if (!checkSsl()) { event.error(Errors.SSL_REQUIRED); response = ErrorPage.error(session, Messages.HTTPS_REQUIRED); return false; } if (!realm.isEnabled()) { event.error(Errors.REALM_DISABLED); response = ErrorPage.error(session, Messages.REALM_NOT_ENABLED); return false; } ClientSessionCode.ParseResult result = ClientSessionCode.parseResult(code, session, realm); clientCode = result.getCode(); if (clientCode == null) { if (result.isClientSessionNotFound()) { // timeout try { ClientSessionModel clientSession = RestartLoginCookie.restartSession(session, realm, code); if (clientSession != null) { event .clone() .detail(Details.RESTART_AFTER_TIMEOUT, "true") .error(Errors.EXPIRED_CODE); response = processFlow( null, clientSession, AUTHENTICATE_PATH, realm.getBrowserFlow(), Messages.LOGIN_TIMEOUT); return false; } } catch (Exception e) { logger.error("failed to parse RestartLoginCookie", e); } } event.error(Errors.INVALID_CODE); response = ErrorPage.error(session, Messages.INVALID_CODE); return false; } ClientSessionModel clientSession = clientCode.getClientSession(); if (clientSession == null) { event.error(Errors.INVALID_CODE); response = ErrorPage.error(session, Messages.INVALID_CODE); return false; } event.detail(Details.CODE_ID, clientSession.getId()); ClientModel client = clientSession.getClient(); if (client == null) { event.error(Errors.CLIENT_NOT_FOUND); response = ErrorPage.error(session, Messages.UNKNOWN_LOGIN_REQUESTER); session.sessions().removeClientSession(realm, clientSession); return false; } if (!client.isEnabled()) { event.error(Errors.CLIENT_NOT_FOUND); response = ErrorPage.error(session, Messages.LOGIN_REQUESTER_NOT_ENABLED); session.sessions().removeClientSession(realm, clientSession); return false; } session.getContext().setClient(client); return true; }