Search in sources :

Example 6 with FederatedIdentityModel

use of org.keycloak.models.FederatedIdentityModel in project keycloak by keycloak.

the class AccountFormService method processFederatedIdentityUpdate.

@Path("identity")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response processFederatedIdentityUpdate() {
    MultivaluedMap<String, String> formData = request.getDecodedFormParameters();
    if (auth == null) {
        return login("identity");
    }
    auth.require(AccountRoles.MANAGE_ACCOUNT);
    csrfCheck(formData);
    UserModel user = auth.getUser();
    String action = formData.getFirst("action");
    String providerId = formData.getFirst("providerId");
    if (Validation.isEmpty(providerId)) {
        setReferrerOnPage();
        return account.setError(Status.OK, Messages.MISSING_IDENTITY_PROVIDER).createResponse(AccountPages.FEDERATED_IDENTITY);
    }
    AccountSocialAction accountSocialAction = AccountSocialAction.getAction(action);
    if (accountSocialAction == null) {
        setReferrerOnPage();
        return account.setError(Status.OK, Messages.INVALID_FEDERATED_IDENTITY_ACTION).createResponse(AccountPages.FEDERATED_IDENTITY);
    }
    if (!realm.getIdentityProvidersStream().anyMatch(model -> Objects.equals(model.getAlias(), providerId))) {
        setReferrerOnPage();
        return account.setError(Status.OK, Messages.IDENTITY_PROVIDER_NOT_FOUND).createResponse(AccountPages.FEDERATED_IDENTITY);
    }
    if (!user.isEnabled()) {
        setReferrerOnPage();
        return account.setError(Status.OK, Messages.ACCOUNT_DISABLED).createResponse(AccountPages.FEDERATED_IDENTITY);
    }
    switch(accountSocialAction) {
        case ADD:
            String redirectUri = UriBuilder.fromUri(Urls.accountFederatedIdentityPage(session.getContext().getUri().getBaseUri(), realm.getName())).build().toString();
            try {
                String nonce = UUID.randomUUID().toString();
                MessageDigest md = MessageDigest.getInstance("SHA-256");
                String input = nonce + auth.getSession().getId() + client.getClientId() + providerId;
                byte[] check = md.digest(input.getBytes(StandardCharsets.UTF_8));
                String hash = Base64Url.encode(check);
                URI linkUrl = Urls.identityProviderLinkRequest(this.session.getContext().getUri().getBaseUri(), providerId, realm.getName());
                linkUrl = UriBuilder.fromUri(linkUrl).queryParam("nonce", nonce).queryParam("hash", hash).queryParam("client_id", client.getClientId()).queryParam("redirect_uri", redirectUri).build();
                return Response.seeOther(linkUrl).build();
            } catch (Exception spe) {
                setReferrerOnPage();
                return account.setError(Response.Status.INTERNAL_SERVER_ERROR, Messages.IDENTITY_PROVIDER_REDIRECT_ERROR).createResponse(AccountPages.FEDERATED_IDENTITY);
            }
        case REMOVE:
            FederatedIdentityModel link = session.users().getFederatedIdentity(realm, user, providerId);
            if (link != null) {
                // Removing last social provider is not possible if you don't have other possibility to authenticate
                if (session.users().getFederatedIdentitiesStream(realm, user).count() > 1 || user.getFederationLink() != null || isPasswordSet(session, realm, user)) {
                    session.users().removeFederatedIdentity(realm, user, providerId);
                    logger.debugv("Social provider {0} removed successfully from user {1}", providerId, user.getUsername());
                    event.event(EventType.REMOVE_FEDERATED_IDENTITY).client(auth.getClient()).user(auth.getUser()).detail(Details.USERNAME, auth.getUser().getUsername()).detail(Details.IDENTITY_PROVIDER, link.getIdentityProvider()).detail(Details.IDENTITY_PROVIDER_USERNAME, link.getUserName()).success();
                    setReferrerOnPage();
                    return account.setSuccess(Messages.IDENTITY_PROVIDER_REMOVED).createResponse(AccountPages.FEDERATED_IDENTITY);
                } else {
                    setReferrerOnPage();
                    return account.setError(Status.OK, Messages.FEDERATED_IDENTITY_REMOVING_LAST_PROVIDER).createResponse(AccountPages.FEDERATED_IDENTITY);
                }
            } else {
                setReferrerOnPage();
                return account.setError(Status.OK, Messages.FEDERATED_IDENTITY_NOT_ACTIVE).createResponse(AccountPages.FEDERATED_IDENTITY);
            }
        default:
            throw new IllegalArgumentException();
    }
}
Also used : UserModel(org.keycloak.models.UserModel) RedirectUtils(org.keycloak.protocol.oidc.utils.RedirectUtils) Arrays(java.util.Arrays) Produces(javax.ws.rs.Produces) EventStoreProvider(org.keycloak.events.EventStoreProvider) Path(javax.ws.rs.Path) LocaleUpdaterProvider(org.keycloak.locale.LocaleUpdaterProvider) AuthenticationSessionManager(org.keycloak.services.managers.AuthenticationSessionManager) Messages(org.keycloak.services.messages.Messages) ResolveRelative(org.keycloak.services.util.ResolveRelative) MediaType(javax.ws.rs.core.MediaType) QueryParam(javax.ws.rs.QueryParam) FormMessage(org.keycloak.models.utils.FormMessage) AuthenticationManager(org.keycloak.services.managers.AuthenticationManager) Consumes(javax.ws.rs.Consumes) ReadOnlyException(org.keycloak.storage.ReadOnlyException) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) Validation(org.keycloak.services.validation.Validation) AppAuthManager(org.keycloak.services.managers.AppAuthManager) Map(java.util.Map) Auth(org.keycloak.services.managers.Auth) UriBuilder(javax.ws.rs.core.UriBuilder) URI(java.net.URI) AuthorizationProvider(org.keycloak.authorization.AuthorizationProvider) Method(java.lang.reflect.Method) Time(org.keycloak.common.util.Time) CredentialValidation(org.keycloak.models.utils.CredentialValidation) UriUtils(org.keycloak.common.util.UriUtils) UserCredentialModel(org.keycloak.models.UserCredentialModel) AccountPages(org.keycloak.forms.account.AccountPages) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RealmModel(org.keycloak.models.RealmModel) Event(org.keycloak.events.Event) EnumMap(java.util.EnumMap) CredentialHelper(org.keycloak.utils.CredentialHelper) Set(java.util.Set) UUID(java.util.UUID) PolicyStore(org.keycloak.authorization.store.PolicyStore) Collectors(java.util.stream.Collectors) EventAuditingAttributeChangeListener(org.keycloak.userprofile.EventAuditingAttributeChangeListener) NotFoundException(javax.ws.rs.NotFoundException) StandardCharsets(java.nio.charset.StandardCharsets) Objects(java.util.Objects) List(java.util.List) Response(javax.ws.rs.core.Response) Details(org.keycloak.events.Details) PermissionTicketStore(org.keycloak.authorization.store.PermissionTicketStore) ForbiddenException(org.keycloak.services.ForbiddenException) UriInfo(javax.ws.rs.core.UriInfo) ClientModel(org.keycloak.models.ClientModel) UserProfile(org.keycloak.userprofile.UserProfile) Scope(org.keycloak.authorization.model.Scope) PathParam(javax.ws.rs.PathParam) RealmsResource(org.keycloak.services.resources.RealmsResource) Profile(org.keycloak.common.Profile) GET(javax.ws.rs.GET) MessageDigest(java.security.MessageDigest) Logger(org.jboss.logging.Logger) AbstractSecuredLocalService(org.keycloak.services.resources.AbstractSecuredLocalService) ServicesLogger(org.keycloak.services.ServicesLogger) PermissionTicket(org.keycloak.authorization.model.PermissionTicket) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LocaleSelectorProvider(org.keycloak.locale.LocaleSelectorProvider) UserModel(org.keycloak.models.UserModel) EventBuilder(org.keycloak.events.EventBuilder) UserProfileProvider(org.keycloak.userprofile.UserProfileProvider) UserConsentManager(org.keycloak.services.managers.UserConsentManager) AccountProvider(org.keycloak.forms.account.AccountProvider) OTPPolicy(org.keycloak.models.OTPPolicy) Base64Url(org.keycloak.common.util.Base64Url) Status(javax.ws.rs.core.Response.Status) ResourceServer(org.keycloak.authorization.model.ResourceServer) FederatedIdentityModel(org.keycloak.models.FederatedIdentityModel) FormParam(javax.ws.rs.FormParam) Errors(org.keycloak.events.Errors) POST(javax.ws.rs.POST) Iterator(java.util.Iterator) KeycloakSession(org.keycloak.models.KeycloakSession) EventType(org.keycloak.events.EventType) IOException(java.io.IOException) UserSessionModel(org.keycloak.models.UserSessionModel) OTPCredentialModel(org.keycloak.models.credential.OTPCredentialModel) JsonSerialization(org.keycloak.util.JsonSerialization) MultivaluedMap(javax.ws.rs.core.MultivaluedMap) Policy(org.keycloak.authorization.model.Policy) AccountRoles(org.keycloak.models.AccountRoles) PasswordCredentialModel(org.keycloak.models.credential.PasswordCredentialModel) ModelException(org.keycloak.models.ModelException) UserProfileContext(org.keycloak.userprofile.UserProfileContext) Urls(org.keycloak.services.Urls) LoginFormsProvider(org.keycloak.forms.login.LoginFormsProvider) ValidationException(org.keycloak.userprofile.ValidationException) Resource(org.keycloak.authorization.model.Resource) ErrorResponse(org.keycloak.services.ErrorResponse) FederatedIdentityModel(org.keycloak.models.FederatedIdentityModel) MessageDigest(java.security.MessageDigest) URI(java.net.URI) ReadOnlyException(org.keycloak.storage.ReadOnlyException) NotFoundException(javax.ws.rs.NotFoundException) ForbiddenException(org.keycloak.services.ForbiddenException) IOException(java.io.IOException) ModelException(org.keycloak.models.ModelException) ValidationException(org.keycloak.userprofile.ValidationException) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes)

Example 7 with FederatedIdentityModel

use of org.keycloak.models.FederatedIdentityModel in project keycloak by keycloak.

the class IdentityBrokerService method getToken.

private Response getToken(String providerId, boolean forceRetrieval) {
    this.event.event(EventType.IDENTITY_PROVIDER_RETRIEVE_TOKEN);
    try {
        AuthenticationManager.AuthResult authResult = new AppAuthManager.BearerTokenAuthenticator(session).setRealm(realmModel).setConnection(clientConnection).setHeaders(request.getHttpHeaders()).authenticate();
        if (authResult != null) {
            AccessToken token = authResult.getToken();
            ClientModel clientModel = authResult.getClient();
            session.getContext().setClient(clientModel);
            ClientModel brokerClient = realmModel.getClientByClientId(Constants.BROKER_SERVICE_CLIENT_ID);
            if (brokerClient == null) {
                return corsResponse(forbidden("Realm has not migrated to support the broker token exchange service"), clientModel);
            }
            if (!canReadBrokerToken(token)) {
                return corsResponse(forbidden("Client [" + clientModel.getClientId() + "] not authorized to retrieve tokens from identity provider [" + providerId + "]."), clientModel);
            }
            IdentityProvider identityProvider = getIdentityProvider(session, realmModel, providerId);
            IdentityProviderModel identityProviderConfig = getIdentityProviderConfig(providerId);
            if (identityProviderConfig.isStoreToken()) {
                FederatedIdentityModel identity = this.session.users().getFederatedIdentity(this.realmModel, authResult.getUser(), providerId);
                if (identity == null) {
                    return corsResponse(badRequest("User [" + authResult.getUser().getId() + "] is not associated with identity provider [" + providerId + "]."), clientModel);
                }
                this.event.success();
                return corsResponse(identityProvider.retrieveToken(session, identity), clientModel);
            }
            return corsResponse(badRequest("Identity Provider [" + providerId + "] does not support this operation."), clientModel);
        }
        return badRequest("Invalid token.");
    } catch (IdentityBrokerException e) {
        return redirectToErrorPage(Response.Status.BAD_GATEWAY, Messages.COULD_NOT_OBTAIN_TOKEN, e, providerId);
    } catch (Exception e) {
        return redirectToErrorPage(Response.Status.BAD_GATEWAY, Messages.UNEXPECTED_ERROR_RETRIEVING_TOKEN, e, providerId);
    }
}
Also used : AuthenticationManager(org.keycloak.services.managers.AuthenticationManager) ClientModel(org.keycloak.models.ClientModel) AccessToken(org.keycloak.representations.AccessToken) FederatedIdentityModel(org.keycloak.models.FederatedIdentityModel) IdentityBrokerException(org.keycloak.broker.provider.IdentityBrokerException) SocialIdentityProvider(org.keycloak.broker.social.SocialIdentityProvider) IdentityProvider(org.keycloak.broker.provider.IdentityProvider) IdentityProviderModel(org.keycloak.models.IdentityProviderModel) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) WebApplicationException(javax.ws.rs.WebApplicationException) IOException(java.io.IOException) IdentityBrokerException(org.keycloak.broker.provider.IdentityBrokerException) OAuthErrorException(org.keycloak.OAuthErrorException) NotFoundException(javax.ws.rs.NotFoundException) ErrorPageException(org.keycloak.services.ErrorPageException)

Example 8 with FederatedIdentityModel

use of org.keycloak.models.FederatedIdentityModel in project keycloak by keycloak.

the class IdentityProviderResource method updateUsersAfterProviderAliasChange.

private static void updateUsersAfterProviderAliasChange(Stream<UserModel> users, String oldProviderId, String newProviderId, RealmModel realm, KeycloakSession session) {
    users.forEach(user -> {
        FederatedIdentityModel federatedIdentity = session.users().getFederatedIdentity(realm, user, oldProviderId);
        if (federatedIdentity != null) {
            // Remove old link first
            session.users().removeFederatedIdentity(realm, user, oldProviderId);
            // And create new
            FederatedIdentityModel newFederatedIdentity = new FederatedIdentityModel(newProviderId, federatedIdentity.getUserId(), federatedIdentity.getUserName(), federatedIdentity.getToken());
            session.users().addFederatedIdentity(realm, user, newFederatedIdentity);
        }
    });
}
Also used : FederatedIdentityModel(org.keycloak.models.FederatedIdentityModel)

Example 9 with FederatedIdentityModel

use of org.keycloak.models.FederatedIdentityModel in project keycloak by keycloak.

the class OIDCIdentityProvider method exchangeStoredToken.

@Override
protected Response exchangeStoredToken(UriInfo uriInfo, EventBuilder event, ClientModel authorizedClient, UserSessionModel tokenUserSession, UserModel tokenSubject) {
    FederatedIdentityModel model = session.users().getFederatedIdentity(authorizedClient.getRealm(), tokenSubject, getConfig().getAlias());
    if (model == null || model.getToken() == null) {
        event.detail(Details.REASON, "requested_issuer is not linked");
        event.error(Errors.INVALID_TOKEN);
        return exchangeNotLinked(uriInfo, authorizedClient, tokenUserSession, tokenSubject);
    }
    try (VaultStringSecret vaultStringSecret = session.vault().getStringSecret(getConfig().getClientSecret())) {
        String modelTokenString = model.getToken();
        AccessTokenResponse tokenResponse = JsonSerialization.readValue(modelTokenString, AccessTokenResponse.class);
        Integer exp = (Integer) tokenResponse.getOtherClaims().get(ACCESS_TOKEN_EXPIRATION);
        if (exp != null && exp < Time.currentTime()) {
            if (tokenResponse.getRefreshToken() == null) {
                return exchangeTokenExpired(uriInfo, authorizedClient, tokenUserSession, tokenSubject);
            }
            String response = getRefreshTokenRequest(session, tokenResponse.getRefreshToken(), getConfig().getClientId(), vaultStringSecret.get().orElse(getConfig().getClientSecret())).asString();
            if (response.contains("error")) {
                logger.debugv("Error refreshing token, refresh token expiration?: {0}", response);
                model.setToken(null);
                session.users().updateFederatedIdentity(authorizedClient.getRealm(), tokenSubject, model);
                event.detail(Details.REASON, "requested_issuer token expired");
                event.error(Errors.INVALID_TOKEN);
                return exchangeTokenExpired(uriInfo, authorizedClient, tokenUserSession, tokenSubject);
            }
            AccessTokenResponse newResponse = JsonSerialization.readValue(response, AccessTokenResponse.class);
            if (newResponse.getExpiresIn() > 0) {
                int accessTokenExpiration = Time.currentTime() + (int) newResponse.getExpiresIn();
                newResponse.getOtherClaims().put(ACCESS_TOKEN_EXPIRATION, accessTokenExpiration);
            }
            if (newResponse.getRefreshToken() == null && tokenResponse.getRefreshToken() != null) {
                newResponse.setRefreshToken(tokenResponse.getRefreshToken());
                newResponse.setRefreshExpiresIn(tokenResponse.getRefreshExpiresIn());
            }
            response = JsonSerialization.writeValueAsString(newResponse);
            String oldToken = tokenUserSession.getNote(FEDERATED_ACCESS_TOKEN);
            if (oldToken != null && oldToken.equals(tokenResponse.getToken())) {
                int accessTokenExpiration = newResponse.getExpiresIn() > 0 ? Time.currentTime() + (int) newResponse.getExpiresIn() : 0;
                tokenUserSession.setNote(FEDERATED_TOKEN_EXPIRATION, Long.toString(accessTokenExpiration));
                tokenUserSession.setNote(FEDERATED_REFRESH_TOKEN, newResponse.getRefreshToken());
                tokenUserSession.setNote(FEDERATED_ACCESS_TOKEN, newResponse.getToken());
                tokenUserSession.setNote(FEDERATED_ID_TOKEN, newResponse.getIdToken());
            }
            model.setToken(response);
            tokenResponse = newResponse;
        } else if (exp != null) {
            tokenResponse.setExpiresIn(exp - Time.currentTime());
        }
        tokenResponse.setIdToken(null);
        tokenResponse.setRefreshToken(null);
        tokenResponse.setRefreshExpiresIn(0);
        tokenResponse.getOtherClaims().clear();
        tokenResponse.getOtherClaims().put(OAuth2Constants.ISSUED_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE);
        tokenResponse.getOtherClaims().put(ACCOUNT_LINK_URL, getLinkingUrl(uriInfo, authorizedClient, tokenUserSession));
        event.success();
        return Response.ok(tokenResponse).type(MediaType.APPLICATION_JSON_TYPE).build();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
Also used : VaultStringSecret(org.keycloak.vault.VaultStringSecret) FederatedIdentityModel(org.keycloak.models.FederatedIdentityModel) IOException(java.io.IOException) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse)

Example 10 with FederatedIdentityModel

use of org.keycloak.models.FederatedIdentityModel in project keycloak by keycloak.

the class TwitterIdentityProvider method exchangeStoredToken.

protected Response exchangeStoredToken(UriInfo uriInfo, ClientModel authorizedClient, UserSessionModel tokenUserSession, UserModel tokenSubject) {
    FederatedIdentityModel model = session.users().getFederatedIdentity(authorizedClient.getRealm(), tokenSubject, getConfig().getAlias());
    if (model == null || model.getToken() == null) {
        return exchangeNotLinked(uriInfo, authorizedClient, tokenUserSession, tokenSubject);
    }
    String accessToken = model.getToken();
    if (accessToken == null) {
        model.setToken(null);
        session.users().updateFederatedIdentity(authorizedClient.getRealm(), tokenSubject, model);
        return exchangeTokenExpired(uriInfo, authorizedClient, tokenUserSession, tokenSubject);
    }
    AccessTokenResponse tokenResponse = new AccessTokenResponse();
    tokenResponse.setToken(accessToken);
    tokenResponse.setIdToken(null);
    tokenResponse.setRefreshToken(null);
    tokenResponse.setRefreshExpiresIn(0);
    tokenResponse.getOtherClaims().clear();
    tokenResponse.getOtherClaims().put(OAuth2Constants.ISSUED_TOKEN_TYPE, TWITTER_TOKEN_TYPE);
    tokenResponse.getOtherClaims().put(ACCOUNT_LINK_URL, getLinkingUrl(uriInfo, authorizedClient, tokenUserSession));
    return Response.ok(tokenResponse).type(MediaType.APPLICATION_JSON_TYPE).build();
}
Also used : FederatedIdentityModel(org.keycloak.models.FederatedIdentityModel) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse)

Aggregations

FederatedIdentityModel (org.keycloak.models.FederatedIdentityModel)22 UserModel (org.keycloak.models.UserModel)6 IOException (java.io.IOException)4 Path (javax.ws.rs.Path)4 NotFoundException (javax.ws.rs.NotFoundException)3 Produces (javax.ws.rs.Produces)3 IdentityProviderMapper (org.keycloak.broker.provider.IdentityProviderMapper)3 ClientModel (org.keycloak.models.ClientModel)3 IdentityProviderModel (org.keycloak.models.IdentityProviderModel)3 KeycloakSessionFactory (org.keycloak.models.KeycloakSessionFactory)3 URI (java.net.URI)2 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)2 ArrayList (java.util.ArrayList)2 List (java.util.List)2 Map (java.util.Map)2 GET (javax.ws.rs.GET)2 POST (javax.ws.rs.POST)2 WebApplicationException (javax.ws.rs.WebApplicationException)2 Response (javax.ws.rs.core.Response)2 SerializedBrokeredIdentityContext (org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext)2