use of org.keycloak.representations.AccessToken in project keycloak by keycloak.
the class TestingOIDCEndpointsApplicationResource method requestAuthenticationChannel.
@POST
@Path("/request-authentication-channel")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public Response requestAuthenticationChannel(@Context HttpHeaders headers, AuthenticationChannelRequest request) {
String rawBearerToken = AppAuthManager.extractAuthorizationHeaderToken(headers);
AccessToken bearerToken;
try {
bearerToken = new JWSInput(rawBearerToken).readJsonContent(AccessToken.class);
} catch (JWSInputException e) {
throw new RuntimeException("Failed to parse bearer token", e);
}
// required
String authenticationChannelId = bearerToken.getId();
if (authenticationChannelId == null)
throw new BadRequestException("missing parameter : " + HttpAuthenticationChannelProvider.AUTHENTICATION_CHANNEL_ID);
String loginHint = request.getLoginHint();
if (loginHint == null)
throw new BadRequestException("missing parameter : " + CibaGrantType.LOGIN_HINT);
if (request.getConsentRequired() == null)
throw new BadRequestException("missing parameter : " + CibaGrantType.IS_CONSENT_REQUIRED);
String scope = request.getScope();
if (scope == null)
throw new BadRequestException("missing parameter : " + OAuth2Constants.SCOPE);
// optional
// for testing purpose
String bindingMessage = request.getBindingMessage();
if (bindingMessage != null && bindingMessage.equals("GODOWN"))
throw new BadRequestException("intentional error : GODOWN");
// only one CIBA flow without binding_message can be accepted per test method by this test mechanism.
if (bindingMessage == null)
bindingMessage = ChannelRequestDummyKey;
authenticationChannelRequests.put(bindingMessage, new TestAuthenticationChannelRequest(request, rawBearerToken));
return Response.status(Status.CREATED).build();
}
use of org.keycloak.representations.AccessToken in project keycloak by keycloak.
the class AbstractMigrationTest method testCredentialsMigratedToNewFormat.
protected void testCredentialsMigratedToNewFormat() {
log.info("testing user's credentials migrated to new format with secretData and credentialData");
// Try to login with password+otp after the migration
try {
oauth.realm(MIGRATION);
oauth.clientId("migration-test-client");
TimeBasedOTP otpGenerator = new TimeBasedOTP("HmacSHA1", 8, 40, 1);
String otp = otpGenerator.generateTOTP("dSdmuHLQhkm54oIm0A0S");
// Try invalid password first
OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("secret", "migration-test-user", "password", otp);
Assert.assertNull(response.getAccessToken());
Assert.assertNotNull(response.getError());
// Try invalid OTP then
response = oauth.doGrantAccessTokenRequest("secret", "migration-test-user", "password2", "invalid");
Assert.assertNull(response.getAccessToken());
Assert.assertNotNull(response.getError());
// Try successful login now
response = oauth.doGrantAccessTokenRequest("secret", "migration-test-user", "password2", otp);
Assert.assertNull(response.getError());
AccessToken accessToken = oauth.verifyToken(response.getAccessToken());
assertEquals("migration-test-user", accessToken.getPreferredUsername());
} catch (Exception e) {
throw new AssertionError("Failed to login with user 'migration-test-user' after migration", e);
}
}
use of org.keycloak.representations.AccessToken in project keycloak by keycloak.
the class TransientSessionTest method loginSuccess.
@Test
public void loginSuccess() throws Exception {
setUpDirectGrantFlowWithSetClientNoteAuthenticator();
oauth.clientId("direct-grant");
// Signal that we want userSession to be transient
oauth.addCustomParameter(SetClientNoteAuthenticator.PREFIX + AuthenticationManager.USER_SESSION_PERSISTENT_STATE, UserSessionModel.SessionPersistenceState.TRANSIENT.toString());
OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("password", "test-user@localhost", "password");
assertEquals(200, response.getStatusCode());
AccessToken accessToken = oauth.verifyToken(response.getAccessToken());
RefreshToken refreshToken = oauth.parseRefreshToken(response.getRefreshToken());
// sessionState is available, but the session was transient and hence not really persisted on the server
assertNotNull(accessToken.getSessionState());
assertEquals(accessToken.getSessionState(), refreshToken.getSessionState());
// Refresh will fail. There is no userSession on the server
OAuthClient.AccessTokenResponse refreshedResponse = oauth.doRefreshTokenRequest(response.getRefreshToken(), "password");
Assert.assertNull(refreshedResponse.getAccessToken());
assertNotNull(refreshedResponse.getError());
Assert.assertEquals("Session not active", refreshedResponse.getErrorDescription());
}
use of org.keycloak.representations.AccessToken in project keycloak by keycloak.
the class HoKTest method refreshTokenRequestByHoKRefreshTokenWithClientCertificate.
@Test
public void refreshTokenRequestByHoKRefreshTokenWithClientCertificate() throws Exception {
oauth.doLogin("test-user@localhost", "password");
EventRepresentation loginEvent = events.expectLogin().assertEvent();
String sessionId = loginEvent.getSessionId();
String codeId = loginEvent.getDetails().get(Details.CODE_ID);
String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
AccessTokenResponse tokenResponse = null;
try (CloseableHttpClient client = MutualTLSUtils.newCloseableHttpClientWithDefaultKeyStoreAndTrustStore()) {
tokenResponse = oauth.doAccessTokenRequest(code, "password", client);
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
verifyHoKTokenDefaultCertThumbPrint(tokenResponse);
AccessToken token = oauth.verifyToken(tokenResponse.getAccessToken());
String refreshTokenString = tokenResponse.getRefreshToken();
RefreshToken refreshToken = oauth.parseRefreshToken(refreshTokenString);
EventRepresentation tokenEvent = events.expectCodeToToken(codeId, sessionId).assertEvent();
Assert.assertNotNull(refreshTokenString);
assertEquals("Bearer", tokenResponse.getTokenType());
Assert.assertThat(token.getExpiration() - getCurrentTime(), allOf(greaterThanOrEqualTo(200), lessThanOrEqualTo(350)));
int actual = refreshToken.getExpiration() - getCurrentTime();
Assert.assertThat(actual, allOf(greaterThanOrEqualTo(1799 - RefreshTokenTest.ALLOWED_CLOCK_SKEW), lessThanOrEqualTo(1800 + RefreshTokenTest.ALLOWED_CLOCK_SKEW)));
assertEquals(sessionId, refreshToken.getSessionState());
setTimeOffset(2);
AccessTokenResponse response = null;
try (CloseableHttpClient client = MutualTLSUtils.newCloseableHttpClientWithDefaultKeyStoreAndTrustStore()) {
response = oauth.doRefreshTokenRequest(refreshTokenString, "password", client);
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
// Success Pattern
expectSuccessfulResponseFromTokenEndpoint(response, sessionId, token, refreshToken, tokenEvent);
verifyHoKTokenDefaultCertThumbPrint(response);
}
use of org.keycloak.representations.AccessToken in project keycloak by keycloak.
the class TokenEndpoint method permissionGrant.
public Response permissionGrant() {
event.detail(Details.AUTH_METHOD, "oauth_credentials");
String accessTokenString = null;
String authorizationHeader = headers.getRequestHeaders().getFirst(HttpHeaders.AUTHORIZATION);
if (authorizationHeader != null && authorizationHeader.toLowerCase().startsWith("bearer")) {
accessTokenString = new AppAuthManager().extractAuthorizationHeaderToken(headers);
}
// public clients don't have secret and should be able to obtain a RPT by providing an access token previously issued by the server
if (accessTokenString != null) {
AccessToken accessToken = Tokens.getAccessToken(session);
if (accessToken == null) {
try {
// In case the access token is invalid because it's expired or the user is disabled, identify the client
// from the access token anyway in order to set correct CORS headers.
AccessToken invalidToken = new JWSInput(accessTokenString).readJsonContent(AccessToken.class);
ClientModel client = realm.getClientByClientId(invalidToken.getIssuedFor());
cors.allowedOrigins(session, client);
event.client(client);
} catch (JWSInputException ignore) {
}
event.error(Errors.INVALID_TOKEN);
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "Invalid bearer token", Status.UNAUTHORIZED);
}
ClientModel client = realm.getClientByClientId(accessToken.getIssuedFor());
session.getContext().setClient(client);
cors.allowedOrigins(session, client);
event.client(client);
}
String claimToken = null;
// claim_token is optional, if provided we just grab it from the request
if (formParams.containsKey("claim_token")) {
claimToken = formParams.get("claim_token").get(0);
}
String claimTokenFormat = formParams.getFirst("claim_token_format");
if (claimToken != null && claimTokenFormat == null) {
claimTokenFormat = AuthorizationTokenService.CLAIM_TOKEN_FORMAT_ID_TOKEN;
}
String subjectToken = formParams.getFirst("subject_token");
if (accessTokenString == null) {
// in case no bearer token is provided, we force client authentication
checkClient();
// if a claim token is provided, we check if the format is a OpenID Connect IDToken and assume the token represents the identity asking for permissions
if (AuthorizationTokenService.CLAIM_TOKEN_FORMAT_ID_TOKEN.equalsIgnoreCase(claimTokenFormat)) {
accessTokenString = claimToken;
} else if (subjectToken != null) {
accessTokenString = subjectToken;
} else {
// Clients need to authenticate in order to obtain a RPT from the server.
// In order to support cases where the client is obtaining permissions on its on behalf, we issue a temporary access token
accessTokenString = AccessTokenResponse.class.cast(clientCredentialsGrant().getEntity()).getToken();
}
}
AuthorizationTokenService.KeycloakAuthorizationRequest authorizationRequest = new AuthorizationTokenService.KeycloakAuthorizationRequest(session.getProvider(AuthorizationProvider.class), tokenManager, event, this.request, cors, clientConnection);
authorizationRequest.setTicket(formParams.getFirst("ticket"));
authorizationRequest.setClaimToken(claimToken);
authorizationRequest.setClaimTokenFormat(claimTokenFormat);
authorizationRequest.setPct(formParams.getFirst("pct"));
String rpt = formParams.getFirst("rpt");
if (rpt != null) {
AccessToken accessToken = session.tokens().decode(rpt, AccessToken.class);
if (accessToken == null) {
event.error(Errors.INVALID_REQUEST);
throw new CorsErrorResponseException(cors, "invalid_rpt", "RPT signature is invalid", Status.FORBIDDEN);
}
authorizationRequest.setRpt(accessToken);
}
authorizationRequest.setScope(formParams.getFirst("scope"));
String audienceParam = formParams.getFirst("audience");
authorizationRequest.setAudience(audienceParam);
authorizationRequest.setSubjectToken(accessTokenString);
event.detail(Details.AUDIENCE, audienceParam);
String submitRequest = formParams.getFirst("submit_request");
authorizationRequest.setSubmitRequest(submitRequest == null ? true : Boolean.valueOf(submitRequest));
// permissions have a format like RESOURCE#SCOPE1,SCOPE2
List<String> permissions = formParams.get("permission");
if (permissions != null) {
event.detail(Details.PERMISSION, String.join("|", permissions));
for (String permission : permissions) {
String[] parts = permission.split("#");
String resource = parts[0];
if (parts.length == 1) {
authorizationRequest.addPermission(resource);
} else {
String[] scopes = parts[1].split(",");
authorizationRequest.addPermission(parts[0], scopes);
}
}
}
Metadata metadata = new Metadata();
String responseIncludeResourceName = formParams.getFirst("response_include_resource_name");
if (responseIncludeResourceName != null) {
metadata.setIncludeResourceName(Boolean.parseBoolean(responseIncludeResourceName));
}
String responsePermissionsLimit = formParams.getFirst("response_permissions_limit");
if (responsePermissionsLimit != null) {
metadata.setLimit(Integer.parseInt(responsePermissionsLimit));
}
metadata.setResponseMode(formParams.getFirst("response_mode"));
authorizationRequest.setMetadata(metadata);
Response authorizationResponse = AuthorizationTokenService.instance().authorize(authorizationRequest);
event.success();
return authorizationResponse;
}
Aggregations