use of org.keycloak.protocol.oidc.grants.ciba.clientpolicy.context.BackchannelTokenRequestContext in project keycloak by keycloak.
the class CibaGrantType method cibaGrant.
public Response cibaGrant() {
ProfileHelper.requireFeature(Profile.Feature.CIBA);
if (!realm.getCibaPolicy().isOIDCCIBAGrantEnabled(client)) {
event.error(Errors.NOT_ALLOWED);
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "Client not allowed OIDC CIBA Grant", Response.Status.BAD_REQUEST);
}
String jwe = formParams.getFirst(AUTH_REQ_ID);
if (jwe == null) {
event.error(Errors.INVALID_CODE);
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "Missing parameter: " + AUTH_REQ_ID, Response.Status.BAD_REQUEST);
}
logger.tracev("CIBA Grant :: authReqId = {0}", jwe);
CIBAAuthenticationRequest request;
try {
request = CIBAAuthenticationRequest.deserialize(session, jwe);
} catch (Exception e) {
logger.warnf("illegal format of auth_req_id : e.getMessage() = %s", e.getMessage());
// Auth Req ID has not put onto cache, no need to remove Auth Req ID.
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "Invalid Auth Req ID", Response.Status.BAD_REQUEST);
}
request.setClient(client);
try {
session.clientPolicy().triggerOnEvent(new BackchannelTokenRequestContext(request, formParams));
} catch (ClientPolicyException cpe) {
event.error(cpe.getError());
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, cpe.getErrorDetail(), Response.Status.BAD_REQUEST);
}
OAuth2DeviceTokenStoreProvider store = session.getProvider(OAuth2DeviceTokenStoreProvider.class);
OAuth2DeviceCodeModel deviceCode = store.getByDeviceCode(realm, request.getId());
if (deviceCode == null) {
// Auth Req ID has not put onto cache, no need to remove Auth Req ID.
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "Invalid " + AUTH_REQ_ID, Response.Status.BAD_REQUEST);
}
if (!request.getIssuedFor().equals(client.getClientId())) {
logDebug("invalid client.", request);
// the client sending this Auth Req ID does not match the client to which keycloak had issued Auth Req ID.
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "unauthorized client", Response.Status.BAD_REQUEST);
}
if (deviceCode.isExpired()) {
logDebug("expired.", request);
throw new CorsErrorResponseException(cors, OAuthErrorException.EXPIRED_TOKEN, "authentication timed out", Response.Status.BAD_REQUEST);
}
if (!store.isPollingAllowed(deviceCode)) {
logDebug("pooling.", request);
throw new CorsErrorResponseException(cors, OAuthErrorException.SLOW_DOWN, "too early to access", Response.Status.BAD_REQUEST);
}
if (deviceCode.isDenied()) {
logDebug("denied.", request);
throw new CorsErrorResponseException(cors, OAuthErrorException.ACCESS_DENIED, "not authorized", Response.Status.BAD_REQUEST);
}
// get corresponding Authentication Channel Result entry
if (deviceCode.isPending()) {
logDebug("not yet authenticated by Authentication Device or auth_req_id has already been used to get tokens.", request);
throw new CorsErrorResponseException(cors, OAuthErrorException.AUTHORIZATION_PENDING, "The authorization request is still pending as the end-user hasn't yet been authenticated.", Response.Status.BAD_REQUEST);
}
UserSessionModel userSession = createUserSession(request, deviceCode.getAdditionalParams());
UserModel user = userSession.getUser();
store.removeDeviceCode(realm, request.getId());
// Compute client scopes again from scope parameter. Check if user still has them granted
// (but in code-to-token request, it could just theoretically happen that they are not available)
String scopeParam = request.getScope();
if (!TokenManager.verifyConsentStillAvailable(session, user, client, TokenManager.getRequestedClientScopes(scopeParam, client))) {
event.error(Errors.NOT_ALLOWED);
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_SCOPE, "Client no longer has requested consent from user", Response.Status.BAD_REQUEST);
}
ClientSessionContext clientSessionCtx = DefaultClientSessionContext.fromClientSessionAndScopeParameter(userSession.getAuthenticatedClientSessionByClient(client.getId()), scopeParam, session);
int authTime = Time.currentTime();
userSession.setNote(AuthenticationManager.AUTH_TIME, String.valueOf(authTime));
return tokenEndpoint.createTokenResponse(user, userSession, clientSessionCtx, scopeParam, true);
}
Aggregations