fix
This commit is contained in:
parent
41cdd9db70
commit
16954fc370
4 changed files with 82 additions and 9 deletions
|
@ -97,6 +97,8 @@ public interface OAuth2Constants {
|
||||||
String AUDIENCE="audience";
|
String AUDIENCE="audience";
|
||||||
String SUBJECT_TOKEN="subject_token";
|
String SUBJECT_TOKEN="subject_token";
|
||||||
String SUBJECT_TOKEN_TYPE="subject_token_type";
|
String SUBJECT_TOKEN_TYPE="subject_token_type";
|
||||||
|
String REQUESTED_TOKEN_TYPE="requested_token_type";
|
||||||
|
String REQUESTED_ISSUER="requested_issuer";
|
||||||
String ACCESS_TOKEN_TYPE="urn:ietf:params:oauth:token-type:access_token";
|
String ACCESS_TOKEN_TYPE="urn:ietf:params:oauth:token-type:access_token";
|
||||||
String REFRESH_TOKEN_TYPE="urn:ietf:params:oauth:token-type:refresh_token";
|
String REFRESH_TOKEN_TYPE="urn:ietf:params:oauth:token-type:refresh_token";
|
||||||
String JWT_TOKEN_TYPE="urn:ietf:params:oauth:token-type:jwt";
|
String JWT_TOKEN_TYPE="urn:ietf:params:oauth:token-type:jwt";
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.keycloak.broker.provider;
|
||||||
|
|
||||||
|
import org.keycloak.models.ClientModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.models.UserSessionModel;
|
||||||
|
import org.keycloak.representations.AccessToken;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public interface TokenExchangeTo {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param authorizedClient client requesting exchange
|
||||||
|
* @param tokenUserSession UserSessionModel of token exchanging from
|
||||||
|
* @param tokenSubject UserModel of token exchanging from
|
||||||
|
* @param token access token representation of token exchanging from
|
||||||
|
* @param params form parameters received for requested exchange
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Response exchangeTo(ClientModel authorizedClient, UserSessionModel tokenUserSession, UserModel tokenSubject, AccessToken token, MultivaluedMap<String, String> params);
|
||||||
|
}
|
|
@ -564,19 +564,43 @@ public class TokenEndpoint {
|
||||||
public Response buildTokenExchange() {
|
public Response buildTokenExchange() {
|
||||||
event.detail(Details.AUTH_METHOD, "oauth_credentials");
|
event.detail(Details.AUTH_METHOD, "oauth_credentials");
|
||||||
|
|
||||||
String scope = formParams.getFirst(OAuth2Constants.SCOPE);
|
|
||||||
String subjectToken = formParams.getFirst(OAuth2Constants.SUBJECT_TOKEN);
|
String subjectToken = formParams.getFirst(OAuth2Constants.SUBJECT_TOKEN);
|
||||||
String subjectTokenType = formParams.getFirst(OAuth2Constants.SUBJECT_TOKEN_TYPE);
|
String subjectTokenType = formParams.getFirst(OAuth2Constants.SUBJECT_TOKEN_TYPE);
|
||||||
|
if (subjectTokenType != null && !subjectTokenType.equals(OAuth2Constants.ACCESS_TOKEN_TYPE)) {
|
||||||
|
event.error(Errors.INVALID_TOKEN);
|
||||||
|
throw new ErrorResponseException(OAuthErrorException.INVALID_TOKEN, "Invalid token type, must be access token", Response.Status.BAD_REQUEST);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
AuthenticationManager.AuthResult authResult = AuthenticationManager.verifyIdentityToken(session, realm, uriInfo, clientConnection, true, true, false, subjectToken, headers);
|
AuthenticationManager.AuthResult authResult = AuthenticationManager.verifyIdentityToken(session, realm, uriInfo, clientConnection, true, true, false, subjectToken, headers);
|
||||||
if (authResult == null) {
|
if (authResult == null) {
|
||||||
event.error(Errors.INVALID_TOKEN);
|
event.error(Errors.INVALID_TOKEN);
|
||||||
throw new ErrorResponseException(OAuthErrorException.INVALID_TOKEN, "Invalid token", Response.Status.BAD_REQUEST);
|
throw new ErrorResponseException(OAuthErrorException.INVALID_TOKEN, "Invalid token", Response.Status.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String requestedIssuer = formParams.getFirst(OAuth2Constants.REQUESTED_ISSUER);
|
||||||
|
|
||||||
|
if (requestedIssuer == null) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return exchangeClientToClient(authResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Response exchangeClientToClient(AuthenticationManager.AuthResult subject) {
|
||||||
|
String requestedTokenType = formParams.getFirst(OAuth2Constants.REQUESTED_TOKEN_TYPE);
|
||||||
|
if (requestedTokenType == null) {
|
||||||
|
requestedTokenType = OAuth2Constants.REFRESH_TOKEN_TYPE;
|
||||||
|
} else if (!requestedTokenType.equals(OAuth2Constants.ACCESS_TOKEN_TYPE) && !requestedTokenType.equals(OAuth2Constants.REFRESH_TOKEN_TYPE)) {
|
||||||
|
event.error(Errors.INVALID_REQUEST);
|
||||||
|
throw new ErrorResponseException("unsupported_requested_token_type", "Unsupported requested token type", Response.Status.BAD_REQUEST);
|
||||||
|
|
||||||
|
}
|
||||||
String audience = formParams.getFirst(OAuth2Constants.AUDIENCE);
|
String audience = formParams.getFirst(OAuth2Constants.AUDIENCE);
|
||||||
if (audience == null) {
|
if (audience == null) {
|
||||||
event.error(Errors.INVALID_REQUEST);
|
event.error(Errors.INVALID_REQUEST);
|
||||||
throw new ErrorResponseException("invalid_audience", "No audience specified", Response.Status.BAD_REQUEST);
|
throw new ErrorResponseException("invalid_audience", "Audience parameter required", Response.Status.BAD_REQUEST);
|
||||||
|
|
||||||
}
|
}
|
||||||
ClientModel targetClient = null;
|
ClientModel targetClient = null;
|
||||||
|
@ -594,7 +618,7 @@ public class TokenEndpoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean exchangeFromAllowed = false;
|
boolean exchangeFromAllowed = false;
|
||||||
for (String aud : authResult.getToken().getAudience()) {
|
for (String aud : subject.getToken().getAudience()) {
|
||||||
ClientModel audClient = realm.getClientByClientId(aud);
|
ClientModel audClient = realm.getClientByClientId(aud);
|
||||||
if (audClient == null) continue;
|
if (audClient == null) continue;
|
||||||
if (audClient.equals(client)) {
|
if (audClient.equals(client)) {
|
||||||
|
@ -617,13 +641,15 @@ public class TokenEndpoint {
|
||||||
throw new ErrorResponseException(OAuthErrorException.ACCESS_DENIED, "Client not allowed to exchange", Response.Status.FORBIDDEN);
|
throw new ErrorResponseException(OAuthErrorException.ACCESS_DENIED, "Client not allowed to exchange", Response.Status.FORBIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String scope = formParams.getFirst(OAuth2Constants.SCOPE);
|
||||||
|
|
||||||
AuthenticationSessionModel authSession = new AuthenticationSessionManager(session).createAuthenticationSession(realm, targetClient, false);
|
AuthenticationSessionModel authSession = new AuthenticationSessionManager(session).createAuthenticationSession(realm, targetClient, false);
|
||||||
authSession.setAuthenticatedUser(authResult.getUser());
|
authSession.setAuthenticatedUser(subject.getUser());
|
||||||
authSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
authSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||||
authSession.setClientNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
|
authSession.setClientNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
|
||||||
authSession.setClientNote(OIDCLoginProtocol.SCOPE_PARAM, scope);
|
authSession.setClientNote(OIDCLoginProtocol.SCOPE_PARAM, scope);
|
||||||
|
|
||||||
UserSessionModel userSession = authResult.getSession();
|
UserSessionModel userSession = subject.getSession();
|
||||||
event.session(userSession);
|
event.session(userSession);
|
||||||
|
|
||||||
AuthenticationManager.setRolesAndMappersInSession(authSession);
|
AuthenticationManager.setRolesAndMappersInSession(authSession);
|
||||||
|
@ -637,10 +663,13 @@ public class TokenEndpoint {
|
||||||
updateUserSessionFromClientAuth(userSession);
|
updateUserSessionFromClientAuth(userSession);
|
||||||
|
|
||||||
TokenManager.AccessTokenResponseBuilder responseBuilder = tokenManager.responseBuilder(realm, targetClient, event, session, userSession, clientSession)
|
TokenManager.AccessTokenResponseBuilder responseBuilder = tokenManager.responseBuilder(realm, targetClient, event, session, userSession, clientSession)
|
||||||
.generateAccessToken()
|
.generateAccessToken();
|
||||||
.generateRefreshToken();
|
|
||||||
responseBuilder.getAccessToken().issuedFor(client.getClientId());
|
responseBuilder.getAccessToken().issuedFor(client.getClientId());
|
||||||
responseBuilder.getRefreshToken().issuedFor(client.getClientId());
|
|
||||||
|
if (requestedTokenType.equals(OAuth2Constants.REFRESH_TOKEN_TYPE)) {
|
||||||
|
responseBuilder.generateRefreshToken();
|
||||||
|
responseBuilder.getRefreshToken().issuedFor(client.getClientId());
|
||||||
|
}
|
||||||
|
|
||||||
String scopeParam = clientSession.getNote(OAuth2Constants.SCOPE);
|
String scopeParam = clientSession.getNote(OAuth2Constants.SCOPE);
|
||||||
if (TokenUtil.isOIDCRequest(scopeParam)) {
|
if (TokenUtil.isOIDCRequest(scopeParam)) {
|
||||||
|
|
|
@ -185,7 +185,7 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
|
||||||
authz.getStoreFactory().getPolicyStore().delete(manageMembersPermission.getId());
|
authz.getStoreFactory().getPolicyStore().delete(manageMembersPermission.getId());
|
||||||
}
|
}
|
||||||
Policy viewMembersPermission = viewMembersPermission(group);
|
Policy viewMembersPermission = viewMembersPermission(group);
|
||||||
if (viewMembersPermission == null) {
|
if (viewMembersPermission != null) {
|
||||||
authz.getStoreFactory().getPolicyStore().delete(viewMembersPermission.getId());
|
authz.getStoreFactory().getPolicyStore().delete(viewMembersPermission.getId());
|
||||||
}
|
}
|
||||||
Policy manageMembershipPermission = manageMembershipPermission(group);
|
Policy manageMembershipPermission = manageMembershipPermission(group);
|
||||||
|
|
Loading…
Reference in a new issue