Search in sources :

Example 56 with AccessTokenResponse

use of org.keycloak.representations.AccessTokenResponse in project keycloak by keycloak.

the class AuthUtil method ensureToken.

public static String ensureToken(ConfigData config) {
    if (config.getExternalToken() != null) {
        return config.getExternalToken();
    }
    checkAuthInfo(config);
    RealmConfigData realmConfig = config.sessionRealmConfigData();
    long now = currentTimeMillis();
    // if it's less than 5s to expiry, renew it
    if (realmConfig.getExpiresAt() - now < 5000) {
        // if it's less than 5s to expiry, fail with credentials expired
        if (realmConfig.getRefreshExpiresAt() != null && realmConfig.getRefreshExpiresAt() - now < 5000) {
            throw new RuntimeException("Session has expired. Login again with '" + OsUtil.CMD + " config credentials'");
        }
        if (realmConfig.getSigExpiresAt() != null && realmConfig.getSigExpiresAt() - now < 5000) {
            throw new RuntimeException("Session has expired. Login again with '" + OsUtil.CMD + " config credentials'");
        }
        try {
            String authorization = null;
            StringBuilder body = new StringBuilder();
            if (realmConfig.getRefreshToken() != null) {
                body.append("grant_type=refresh_token").append("&refresh_token=").append(realmConfig.getRefreshToken());
            } else {
                body.append("grant_type=").append(realmConfig.getGrantTypeForAuthentication());
            }
            body.append("&client_id=").append(urlencode(realmConfig.getClientId()));
            if (realmConfig.getSigningToken() != null) {
                body.append("&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer").append("&client_assertion=").append(realmConfig.getSigningToken());
            } else if (realmConfig.getSecret() != null) {
                authorization = BasicAuthHelper.createHeader(realmConfig.getClientId(), realmConfig.getSecret());
            }
            InputStream result = doPost(realmConfig.serverUrl() + "/realms/" + realmConfig.realm() + "/protocol/openid-connect/token", APPLICATION_FORM_URL_ENCODED, APPLICATION_JSON, body.toString(), authorization);
            AccessTokenResponse token = JsonSerialization.readValue(result, AccessTokenResponse.class);
            saveMergeConfig(cfg -> {
                RealmConfigData realmData = cfg.sessionRealmConfigData();
                realmData.setToken(token.getToken());
                realmData.setRefreshToken(token.getRefreshToken());
                realmData.setExpiresAt(currentTimeMillis() + token.getExpiresIn() * 1000);
                if (token.getRefreshToken() != null) {
                    realmData.setRefreshExpiresAt(currentTimeMillis() + token.getRefreshExpiresIn() * 1000);
                }
            });
            return token.getToken();
        } catch (Exception e) {
            throw new RuntimeException("Failed to refresh access token - " + e.getMessage(), e);
        }
    }
    return realmConfig.getToken();
}
Also used : RealmConfigData(org.keycloak.client.admin.cli.config.RealmConfigData) InputStream(java.io.InputStream) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse) IOException(java.io.IOException) UnsupportedEncodingException(java.io.UnsupportedEncodingException)

Example 57 with AccessTokenResponse

use of org.keycloak.representations.AccessTokenResponse in project keycloak by keycloak.

the class OIDCIdentityProvider method getFederatedIdentity.

@Override
public BrokeredIdentityContext getFederatedIdentity(String response) {
    AccessTokenResponse tokenResponse = null;
    try {
        tokenResponse = JsonSerialization.readValue(response, AccessTokenResponse.class);
    } catch (IOException e) {
        throw new IdentityBrokerException("Could not decode access token response.", e);
    }
    String accessToken = verifyAccessToken(tokenResponse);
    String encodedIdToken = tokenResponse.getIdToken();
    JsonWebToken idToken = validateToken(encodedIdToken);
    try {
        BrokeredIdentityContext identity = extractIdentity(tokenResponse, accessToken, idToken);
        if (!identity.getId().equals(idToken.getSubject())) {
            throw new IdentityBrokerException("Mismatch between the subject in the id_token and the subject from the user_info endpoint");
        }
        identity.getContextData().put(BROKER_NONCE_PARAM, idToken.getOtherClaims().get(OIDCLoginProtocol.NONCE_PARAM));
        if (getConfig().isStoreToken()) {
            if (tokenResponse.getExpiresIn() > 0) {
                long accessTokenExpiration = Time.currentTime() + tokenResponse.getExpiresIn();
                tokenResponse.getOtherClaims().put(ACCESS_TOKEN_EXPIRATION, accessTokenExpiration);
                response = JsonSerialization.writeValueAsString(tokenResponse);
            }
            identity.setToken(response);
        }
        return identity;
    } catch (Exception e) {
        throw new IdentityBrokerException("Could not fetch attributes from userinfo endpoint.", e);
    }
}
Also used : IdentityBrokerException(org.keycloak.broker.provider.IdentityBrokerException) IOException(java.io.IOException) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse) JsonWebToken(org.keycloak.representations.JsonWebToken) BrokeredIdentityContext(org.keycloak.broker.provider.BrokeredIdentityContext) OAuthErrorException(org.keycloak.OAuthErrorException) ErrorResponseException(org.keycloak.services.ErrorResponseException) JWSInputException(org.keycloak.jose.jws.JWSInputException) IOException(java.io.IOException) IdentityBrokerException(org.keycloak.broker.provider.IdentityBrokerException)

Example 58 with AccessTokenResponse

use of org.keycloak.representations.AccessTokenResponse in project keycloak by keycloak.

the class OIDCIdentityProvider method getIDTokenForLogout.

private String getIDTokenForLogout(KeycloakSession session, UserSessionModel userSession) {
    String tokenExpirationString = userSession.getNote(FEDERATED_TOKEN_EXPIRATION);
    long exp = tokenExpirationString == null ? 0 : Long.parseLong(tokenExpirationString);
    int currentTime = Time.currentTime();
    if (exp > 0 && currentTime > exp) {
        String response = refreshTokenForLogout(session, userSession);
        AccessTokenResponse tokenResponse = null;
        try {
            tokenResponse = JsonSerialization.readValue(response, AccessTokenResponse.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return tokenResponse.getIdToken();
    } else {
        return userSession.getNote(FEDERATED_ID_TOKEN);
    }
}
Also used : IOException(java.io.IOException) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse)

Example 59 with AccessTokenResponse

use of org.keycloak.representations.AccessTokenResponse 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 60 with AccessTokenResponse

use of org.keycloak.representations.AccessTokenResponse in project keycloak by keycloak.

the class AbstractOAuth2IdentityProvider method exchangeSessionToken.

protected Response exchangeSessionToken(UriInfo uriInfo, EventBuilder event, ClientModel authorizedClient, UserSessionModel tokenUserSession, UserModel tokenSubject) {
    String accessToken = tokenUserSession.getNote(FEDERATED_ACCESS_TOKEN);
    if (accessToken == null) {
        event.detail(Details.REASON, "requested_issuer is not linked");
        event.error(Errors.INVALID_TOKEN);
        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, 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();
}
Also used : AccessTokenResponse(org.keycloak.representations.AccessTokenResponse)

Aggregations

AccessTokenResponse (org.keycloak.representations.AccessTokenResponse)73 Response (javax.ws.rs.core.Response)30 Test (org.junit.Test)29 OAuthClient (org.keycloak.testsuite.util.OAuthClient)25 Client (javax.ws.rs.client.Client)24 AbstractKeycloakTest (org.keycloak.testsuite.AbstractKeycloakTest)17 Form (javax.ws.rs.core.Form)15 WebTarget (javax.ws.rs.client.WebTarget)14 AccessToken (org.keycloak.representations.AccessToken)14 IOException (java.io.IOException)12 ClientResource (org.keycloak.admin.client.resource.ClientResource)7 AuthorizationResponse (org.keycloak.representations.idm.authorization.AuthorizationResponse)7 AuthzClient (org.keycloak.authorization.client.AuthzClient)5 PermissionRequest (org.keycloak.representations.idm.authorization.PermissionRequest)5 CorsErrorResponseException (org.keycloak.services.CorsErrorResponseException)5 UncaughtServerErrorExpected (org.keycloak.testsuite.arquillian.annotation.UncaughtServerErrorExpected)5 InputStream (java.io.InputStream)4 URI (java.net.URI)4 NameValuePair (org.apache.http.NameValuePair)4 UrlEncodedFormEntity (org.apache.http.client.entity.UrlEncodedFormEntity)4