use of org.keycloak.models.OAuth2DeviceTokenStoreProvider in project keycloak by keycloak.
the class DeviceEndpoint method verifyUserCode.
/**
* This endpoint is used by end-users to start the flow to authorize a device.
*
* @param userCode the user code to authorize
* @return
*/
@GET
public Response verifyUserCode(@QueryParam("user_code") String userCode) {
event.event(EventType.OAUTH2_DEVICE_VERIFY_USER_CODE);
checkSsl();
checkRealm();
// So back button doesn't work
CacheControlUtil.noBackButtonCacheControlHeader();
// code is not known, we can infer the client neither. ask the user to provide the code.
if (StringUtil.isNullOrEmpty(userCode)) {
return createVerificationPage(null);
} else {
// code exists, probably due to using a verification_uri_complete. Start the authentication considering the client
// that started the flow.
OAuth2DeviceTokenStoreProvider store = session.getProvider(OAuth2DeviceTokenStoreProvider.class);
OAuth2DeviceUserCodeProvider userCodeProvider = session.getProvider(OAuth2DeviceUserCodeProvider.class);
String formattedUserCode = userCodeProvider.format(userCode);
OAuth2DeviceCodeModel deviceCode = store.getByUserCode(realm, formattedUserCode);
if (deviceCode == null) {
return invalidUserCodeResponse(Messages.OAUTH2_DEVICE_INVALID_USER_CODE, "device code not found (it may already have been used)");
}
if (!deviceCode.isPending()) {
event.detail("device_code_user_session_id", deviceCode.getUserSessionId());
return invalidUserCodeResponse(Messages.OAUTH2_DEVICE_INVALID_USER_CODE, "device code already used and not yet deleted");
}
if (deviceCode.isDenied()) {
return invalidUserCodeResponse(Messages.OAUTH2_DEVICE_INVALID_USER_CODE, "device code denied");
}
if (deviceCode.isExpired()) {
return invalidUserCodeResponse(Messages.OAUTH2_DEVICE_EXPIRED_USER_CODE, "device code expired");
}
return processVerification(deviceCode, formattedUserCode);
}
}
use of org.keycloak.models.OAuth2DeviceTokenStoreProvider in project keycloak by keycloak.
the class BackchannelAuthenticationCallbackEndpoint method cancelRequest.
private void cancelRequest(String authResultId) {
OAuth2DeviceTokenStoreProvider store = session.getProvider(OAuth2DeviceTokenStoreProvider.class);
OAuth2DeviceCodeModel userCode = store.getByUserCode(realm, authResultId);
store.removeDeviceCode(realm, userCode.getDeviceCode());
store.removeUserCode(realm, authResultId);
}
use of org.keycloak.models.OAuth2DeviceTokenStoreProvider in project keycloak by keycloak.
the class BackchannelAuthenticationCallbackEndpoint method verifyAuthenticationRequest.
private BackchannelAuthCallbackContext verifyAuthenticationRequest(HttpHeaders headers) {
String rawBearerToken = AppAuthManager.extractAuthorizationHeaderTokenOrReturnNull(headers);
if (rawBearerToken == null) {
throw new ErrorResponseException(OAuthErrorException.INVALID_TOKEN, "Invalid token", Response.Status.UNAUTHORIZED);
}
AccessToken bearerToken;
try {
bearerToken = TokenVerifier.createWithoutSignature(session.tokens().decode(rawBearerToken, AccessToken.class)).withDefaultChecks().realmUrl(Urls.realmIssuer(session.getContext().getUri().getBaseUri(), realm.getName())).checkActive(true).audience(Urls.realmIssuer(session.getContext().getUri().getBaseUri(), realm.getName())).verify().getToken();
} catch (Exception e) {
event.error(Errors.INVALID_TOKEN);
// authentication channel id format is invalid or it has already been used
throw new ErrorResponseException(OAuthErrorException.INVALID_TOKEN, "Invalid token", Response.Status.FORBIDDEN);
}
OAuth2DeviceTokenStoreProvider store = session.getProvider(OAuth2DeviceTokenStoreProvider.class);
OAuth2DeviceCodeModel deviceCode = store.getByUserCode(realm, bearerToken.getId());
if (deviceCode == null) {
throw new ErrorResponseException(OAuthErrorException.INVALID_TOKEN, "Invalid token", Response.Status.FORBIDDEN);
}
if (!deviceCode.isPending()) {
cancelRequest(bearerToken.getId());
throw new ErrorResponseException(OAuthErrorException.INVALID_TOKEN, "Invalid token", Response.Status.FORBIDDEN);
}
ClientModel issuedFor = realm.getClientByClientId(bearerToken.getIssuedFor());
if (issuedFor == null || !issuedFor.isEnabled()) {
throw new ErrorResponseException(OAuthErrorException.INVALID_REQUEST, "Invalid token recipient", Response.Status.BAD_REQUEST);
}
if (!deviceCode.getClientId().equals(issuedFor.getClientId())) {
throw new ErrorResponseException(OAuthErrorException.INVALID_REQUEST, "Token recipient mismatch", Response.Status.BAD_REQUEST);
}
session.getContext().setClient(issuedFor);
event.client(issuedFor);
return new BackchannelAuthCallbackContext(bearerToken, deviceCode);
}
use of org.keycloak.models.OAuth2DeviceTokenStoreProvider in project keycloak by keycloak.
the class BackchannelAuthenticationCallbackEndpoint method denyRequest.
private void denyRequest(AccessToken authReqId, Status status) {
if (CANCELLED.equals(status)) {
event.error(Errors.NOT_ALLOWED);
} else {
event.error(Errors.CONSENT_DENIED);
}
OAuth2DeviceTokenStoreProvider store = session.getProvider(OAuth2DeviceTokenStoreProvider.class);
store.deny(realm, authReqId.getId());
}
use of org.keycloak.models.OAuth2DeviceTokenStoreProvider in project keycloak by keycloak.
the class BackchannelAuthenticationCallbackEndpoint method approveRequest.
private void approveRequest(AccessToken authReqId, Map<String, String> additionalParams) {
OAuth2DeviceTokenStoreProvider store = session.getProvider(OAuth2DeviceTokenStoreProvider.class);
store.approve(realm, authReqId.getId(), "fake", additionalParams);
}
Aggregations