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();
}
}
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);
}
}
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);
}
});
}
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);
}
}
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();
}
Aggregations