Search in sources :

Example 56 with RefreshToken

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

the class LogoutEndpoint method logoutToken.

/**
 * Logout a session via a non-browser invocation.  Similar signature to refresh token except there is no grant_type.
 * You must pass in the refresh token and
 * authenticate the client if it is not public.
 *
 * If the client is a confidential client
 * you must include the client-id and secret in an Basic Auth Authorization header.
 *
 * If the client is a public client, then you must include a "client_id" form parameter.
 *
 * returns 204 if successful, 400 if not with a json error response.
 *
 * @return
 */
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response logoutToken() {
    cors = Cors.add(request).auth().allowedMethods("POST").auth().exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS);
    MultivaluedMap<String, String> form = request.getDecodedFormParameters();
    checkSsl();
    event.event(EventType.LOGOUT);
    ClientModel client = authorizeClient();
    String refreshToken = form.getFirst(OAuth2Constants.REFRESH_TOKEN);
    if (refreshToken == null) {
        event.error(Errors.INVALID_TOKEN);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "No refresh token", Response.Status.BAD_REQUEST);
    }
    try {
        session.clientPolicy().triggerOnEvent(new LogoutRequestContext(form));
    } catch (ClientPolicyException cpe) {
        throw new CorsErrorResponseException(cors, cpe.getError(), cpe.getErrorDetail(), cpe.getErrorStatus());
    }
    RefreshToken token = null;
    try {
        // KEYCLOAK-6771 Certificate Bound Token
        token = tokenManager.verifyRefreshToken(session, realm, client, request, refreshToken, false);
        boolean offline = TokenUtil.TOKEN_TYPE_OFFLINE.equals(token.getType());
        UserSessionModel userSessionModel;
        if (offline) {
            UserSessionManager sessionManager = new UserSessionManager(session);
            userSessionModel = sessionManager.findOfflineUserSession(realm, token.getSessionState());
        } else {
            userSessionModel = session.sessions().getUserSession(realm, token.getSessionState());
        }
        if (userSessionModel != null) {
            checkTokenIssuedAt(token, userSessionModel);
            logout(userSessionModel, offline);
        }
    } catch (OAuthErrorException e) {
        // KEYCLOAK-6771 Certificate Bound Token
        if (MtlsHoKTokenUtil.CERT_VERIFY_ERROR_DESC.equals(e.getDescription())) {
            event.error(Errors.NOT_ALLOWED);
            throw new CorsErrorResponseException(cors, e.getError(), e.getDescription(), Response.Status.UNAUTHORIZED);
        } else {
            event.error(Errors.INVALID_TOKEN);
            throw new CorsErrorResponseException(cors, e.getError(), e.getDescription(), Response.Status.BAD_REQUEST);
        }
    }
    return cors.builder(Response.noContent()).build();
}
Also used : UserSessionManager(org.keycloak.services.managers.UserSessionManager) ClientModel(org.keycloak.models.ClientModel) UserSessionModel(org.keycloak.models.UserSessionModel) RefreshToken(org.keycloak.representations.RefreshToken) OAuthErrorException(org.keycloak.OAuthErrorException) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) LogoutRequestContext(org.keycloak.services.clientpolicy.context.LogoutRequestContext) ClientPolicyException(org.keycloak.services.clientpolicy.ClientPolicyException) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes)

Example 57 with RefreshToken

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

the class TokenManager method refreshAccessToken.

public RefreshResult refreshAccessToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, ClientModel authorizedClient, String encodedRefreshToken, EventBuilder event, HttpHeaders headers, HttpRequest request) throws OAuthErrorException {
    RefreshToken refreshToken = verifyRefreshToken(session, realm, authorizedClient, request, encodedRefreshToken, true);
    event.user(refreshToken.getSubject()).session(refreshToken.getSessionState()).detail(Details.REFRESH_TOKEN_ID, refreshToken.getId()).detail(Details.REFRESH_TOKEN_TYPE, refreshToken.getType());
    TokenValidation validation = validateToken(session, uriInfo, connection, realm, refreshToken, headers);
    AuthenticatedClientSessionModel clientSession = validation.clientSessionCtx.getClientSession();
    // validate authorizedClient is same as validated client
    if (!clientSession.getClient().getId().equals(authorizedClient.getId())) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token. Token client and authorized client don't match");
    }
    validateTokenReuseForRefresh(session, realm, refreshToken, validation);
    int currentTime = Time.currentTime();
    clientSession.setTimestamp(currentTime);
    validation.userSession.setLastSessionRefresh(currentTime);
    if (refreshToken.getAuthorization() != null) {
        validation.newToken.setAuthorization(refreshToken.getAuthorization());
    }
    AccessTokenResponseBuilder responseBuilder = responseBuilder(realm, authorizedClient, event, session, validation.userSession, validation.clientSessionCtx).accessToken(validation.newToken);
    if (OIDCAdvancedConfigWrapper.fromClientModel(authorizedClient).isUseRefreshToken()) {
        responseBuilder.generateRefreshToken();
    }
    if (validation.newToken.getAuthorization() != null && OIDCAdvancedConfigWrapper.fromClientModel(authorizedClient).isUseRefreshToken()) {
        responseBuilder.getRefreshToken().setAuthorization(validation.newToken.getAuthorization());
    }
    // KEYCLOAK-6771 Certificate Bound Token
    // https://tools.ietf.org/html/draft-ietf-oauth-mtls-08#section-3.1
    // bind refreshed access and refresh token with Client Certificate
    AccessToken.CertConf certConf = refreshToken.getCertConf();
    if (certConf != null) {
        responseBuilder.getAccessToken().setCertConf(certConf);
        if (OIDCAdvancedConfigWrapper.fromClientModel(authorizedClient).isUseRefreshToken()) {
            responseBuilder.getRefreshToken().setCertConf(certConf);
        }
    }
    String scopeParam = clientSession.getNote(OAuth2Constants.SCOPE);
    if (TokenUtil.isOIDCRequest(scopeParam)) {
        responseBuilder.generateIDToken().generateAccessTokenHash();
    }
    AccessTokenResponse res = responseBuilder.build();
    return new RefreshResult(res, TokenUtil.TOKEN_TYPE_OFFLINE.equals(refreshToken.getType()));
}
Also used : RefreshToken(org.keycloak.representations.RefreshToken) OAuthErrorException(org.keycloak.OAuthErrorException) AccessToken(org.keycloak.representations.AccessToken) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse)

Example 58 with RefreshToken

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

the class ClientAuthSignedJWTTest method testServiceAccountAndLogoutSuccess.

// TEST SUCCESS
@Test
public void testServiceAccountAndLogoutSuccess() throws Exception {
    String client1Jwt = getClient1SignedJWT();
    OAuthClient.AccessTokenResponse response = doClientCredentialsGrantRequest(client1Jwt);
    assertEquals(200, response.getStatusCode());
    AccessToken accessToken = oauth.verifyToken(response.getAccessToken());
    RefreshToken refreshToken = oauth.parseRefreshToken(response.getRefreshToken());
    events.expectClientLogin().client("client1").user(client1SAUserId).session(accessToken.getSessionState()).detail(Details.TOKEN_ID, accessToken.getId()).detail(Details.REFRESH_TOKEN_ID, refreshToken.getId()).detail(Details.USERNAME, ServiceAccountConstants.SERVICE_ACCOUNT_USER_PREFIX + "client1").detail(Details.CLIENT_AUTH_METHOD, JWTClientAuthenticator.PROVIDER_ID).assertEvent();
    assertEquals(accessToken.getSessionState(), refreshToken.getSessionState());
    client1Jwt = getClient1SignedJWT();
    OAuthClient.AccessTokenResponse refreshedResponse = doRefreshTokenRequest(response.getRefreshToken(), client1Jwt);
    AccessToken refreshedAccessToken = oauth.verifyToken(refreshedResponse.getAccessToken());
    RefreshToken refreshedRefreshToken = oauth.parseRefreshToken(refreshedResponse.getRefreshToken());
    assertEquals(accessToken.getSessionState(), refreshedAccessToken.getSessionState());
    assertEquals(accessToken.getSessionState(), refreshedRefreshToken.getSessionState());
    events.expectRefresh(refreshToken.getId(), refreshToken.getSessionState()).user(client1SAUserId).client("client1").detail(Details.CLIENT_AUTH_METHOD, JWTClientAuthenticator.PROVIDER_ID).assertEvent();
    // Logout and assert refresh will fail
    HttpResponse logoutResponse = doLogout(response.getRefreshToken(), getClient1SignedJWT());
    assertEquals(204, logoutResponse.getStatusLine().getStatusCode());
    events.expectLogout(accessToken.getSessionState()).client("client1").user(client1SAUserId).removeDetail(Details.REDIRECT_URI).detail(Details.CLIENT_AUTH_METHOD, JWTClientAuthenticator.PROVIDER_ID).assertEvent();
    response = doRefreshTokenRequest(response.getRefreshToken(), getClient1SignedJWT());
    assertEquals(400, response.getStatusCode());
    assertEquals("invalid_grant", response.getError());
    events.expectRefresh(refreshToken.getId(), refreshToken.getSessionState()).client("client1").user(client1SAUserId).removeDetail(Details.TOKEN_ID).removeDetail(Details.UPDATED_REFRESH_TOKEN_ID).detail(Details.CLIENT_AUTH_METHOD, JWTClientAuthenticator.PROVIDER_ID).error(Errors.INVALID_TOKEN).assertEvent();
}
Also used : RefreshToken(org.keycloak.representations.RefreshToken) OAuthClient(org.keycloak.testsuite.util.OAuthClient) AccessToken(org.keycloak.representations.AccessToken) HttpResponse(org.apache.http.HttpResponse) CloseableHttpResponse(org.apache.http.client.methods.CloseableHttpResponse) AbstractKeycloakTest(org.keycloak.testsuite.AbstractKeycloakTest) Test(org.junit.Test)

Example 59 with RefreshToken

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

the class ClientAuthSignedJWTTest method testDirectGrantRequestSuccess.

@Test
public void testDirectGrantRequestSuccess() throws Exception {
    oauth.clientId("client2");
    OAuthClient.AccessTokenResponse response = doGrantAccessTokenRequest("test-user@localhost", "password", getClient2SignedJWT());
    assertEquals(200, response.getStatusCode());
    AccessToken accessToken = oauth.verifyToken(response.getAccessToken());
    RefreshToken refreshToken = oauth.parseRefreshToken(response.getRefreshToken());
    events.expectLogin().client("client2").session(accessToken.getSessionState()).detail(Details.GRANT_TYPE, OAuth2Constants.PASSWORD).detail(Details.TOKEN_ID, accessToken.getId()).detail(Details.REFRESH_TOKEN_ID, refreshToken.getId()).detail(Details.USERNAME, "test-user@localhost").detail(Details.CLIENT_AUTH_METHOD, JWTClientAuthenticator.PROVIDER_ID).removeDetail(Details.CODE_ID).removeDetail(Details.REDIRECT_URI).removeDetail(Details.CONSENT).assertEvent();
}
Also used : RefreshToken(org.keycloak.representations.RefreshToken) OAuthClient(org.keycloak.testsuite.util.OAuthClient) AccessToken(org.keycloak.representations.AccessToken) AbstractKeycloakTest(org.keycloak.testsuite.AbstractKeycloakTest) Test(org.junit.Test)

Example 60 with RefreshToken

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

the class HoKTest method expectSuccessfulResponseFromTokenEndpoint.

private void expectSuccessfulResponseFromTokenEndpoint(OAuthClient oauth, String username, AccessTokenResponse response, String sessionId, AccessToken token, RefreshToken refreshToken, EventRepresentation tokenEvent) {
    AccessToken refreshedToken = oauth.verifyToken(response.getAccessToken());
    RefreshToken refreshedRefreshToken = oauth.parseRefreshToken(response.getRefreshToken());
    if (refreshedToken.getCertConf() != null) {
        log.warnf("refreshed access token's cnf-x5t#256 = %s", refreshedToken.getCertConf().getCertThumbprint());
        log.warnf("refreshed refresh token's cnf-x5t#256 = %s", refreshedRefreshToken.getCertConf().getCertThumbprint());
    }
    assertEquals(200, response.getStatusCode());
    assertEquals(sessionId, refreshedToken.getSessionState());
    assertEquals(sessionId, refreshedRefreshToken.getSessionState());
    Assert.assertThat(response.getExpiresIn(), allOf(greaterThanOrEqualTo(250), lessThanOrEqualTo(300)));
    Assert.assertThat(refreshedToken.getExpiration() - getCurrentTime(), allOf(greaterThanOrEqualTo(250 - RefreshTokenTest.ALLOWED_CLOCK_SKEW), lessThanOrEqualTo(300 + RefreshTokenTest.ALLOWED_CLOCK_SKEW)));
    Assert.assertThat(refreshedToken.getExpiration() - token.getExpiration(), allOf(greaterThanOrEqualTo(1), lessThanOrEqualTo(10)));
    Assert.assertThat(refreshedRefreshToken.getExpiration() - refreshToken.getExpiration(), allOf(greaterThanOrEqualTo(1), lessThanOrEqualTo(10)));
    Assert.assertNotEquals(token.getId(), refreshedToken.getId());
    Assert.assertNotEquals(refreshToken.getId(), refreshedRefreshToken.getId());
    assertEquals("Bearer", response.getTokenType());
    assertEquals(findUserByUsername(adminClient.realm("test"), username).getId(), refreshedToken.getSubject());
    Assert.assertNotEquals(username, refreshedToken.getSubject());
    assertEquals(2, refreshedToken.getRealmAccess().getRoles().size());
    Assert.assertTrue(refreshedToken.getRealmAccess().isUserInRole("user"));
    assertEquals(1, refreshedToken.getResourceAccess(oauth.getClientId()).getRoles().size());
    Assert.assertTrue(refreshedToken.getResourceAccess(oauth.getClientId()).isUserInRole("customer-user"));
    EventRepresentation refreshEvent = events.expectRefresh(tokenEvent.getDetails().get(Details.REFRESH_TOKEN_ID), sessionId).user(AssertEvents.isUUID()).assertEvent();
    Assert.assertNotEquals(tokenEvent.getDetails().get(Details.TOKEN_ID), refreshEvent.getDetails().get(Details.TOKEN_ID));
    Assert.assertNotEquals(tokenEvent.getDetails().get(Details.REFRESH_TOKEN_ID), refreshEvent.getDetails().get(Details.UPDATED_REFRESH_TOKEN_ID));
    setTimeOffset(0);
}
Also used : RefreshToken(org.keycloak.representations.RefreshToken) AccessToken(org.keycloak.representations.AccessToken) EventRepresentation(org.keycloak.representations.idm.EventRepresentation)

Aggregations

RefreshToken (org.keycloak.representations.RefreshToken)68 OAuthClient (org.keycloak.testsuite.util.OAuthClient)50 AccessToken (org.keycloak.representations.AccessToken)45 Test (org.junit.Test)34 AbstractKeycloakTest (org.keycloak.testsuite.AbstractKeycloakTest)29 EventRepresentation (org.keycloak.representations.idm.EventRepresentation)27 JWSInput (org.keycloak.jose.jws.JWSInput)10 ClientRepresentation (org.keycloak.representations.idm.ClientRepresentation)6 AbstractTestRealmKeycloakTest (org.keycloak.testsuite.AbstractTestRealmKeycloakTest)6 IOException (java.io.IOException)5 HttpResponse (org.apache.http.HttpResponse)5 JWSHeader (org.keycloak.jose.jws.JWSHeader)5 IDToken (org.keycloak.representations.IDToken)5 CloseableHttpResponse (org.apache.http.client.methods.CloseableHttpResponse)4 ClientResource (org.keycloak.admin.client.resource.ClientResource)4 OIDCClientRepresentation (org.keycloak.representations.oidc.OIDCClientRepresentation)4 ClientPolicyException (org.keycloak.services.clientpolicy.ClientPolicyException)4 AccessTokenResponse (org.keycloak.testsuite.util.OAuthClient.AccessTokenResponse)4 KeyPair (java.security.KeyPair)3 PrivateKey (java.security.PrivateKey)3