/*
* Copyright (c) 2013, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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.wso2.carbon.identity.oauth2.authz;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.oltu.oauth2.common.error.OAuthError;
import org.wso2.carbon.identity.oauth.dao.OAuthAppDO;
import org.wso2.carbon.identity.oauth.IdentityOAuthAdminException;
import org.wso2.carbon.identity.oauth.cache.AppInfoCache;
import org.wso2.carbon.identity.oauth.common.OAuthConstants;
import org.wso2.carbon.identity.oauth.common.exception.InvalidOAuthClientException;
import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration;
import org.wso2.carbon.identity.oauth.dao.OAuthAppDAO;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
import org.wso2.carbon.identity.oauth2.authz.handlers.ResponseTypeHandler;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AuthorizeReqDTO;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AuthorizeRespDTO;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
import org.wso2.carbon.utils.CarbonUtils;
import java.util.HashMap;
import java.util.Map;
public class AuthorizationHandlerManager {
private static Log log = LogFactory.getLog(AuthorizationHandlerManager.class);
private static AuthorizationHandlerManager instance;
private Map<String, ResponseTypeHandler> responseHandlers = new HashMap<>();
private AppInfoCache appInfoCache;
private AuthorizationHandlerManager() throws IdentityOAuth2Exception {
responseHandlers = OAuthServerConfiguration.getInstance().getSupportedResponseTypes();
appInfoCache = AppInfoCache.getInstance();
if (appInfoCache != null) {
if (log.isDebugEnabled()) {
log.debug("Successfully created AppInfoCache under " + OAuthConstants.OAUTH_CACHE_MANAGER);
}
} else {
log.error("Error while creating AppInfoCache");
}
}
public static AuthorizationHandlerManager getInstance() throws IdentityOAuth2Exception {
CarbonUtils.checkSecurity();
if (instance == null) {
synchronized (AuthorizationHandlerManager.class) {
if (instance == null) {
instance = new AuthorizationHandlerManager();
}
}
}
return instance;
}
public OAuth2AuthorizeRespDTO handleAuthorization(OAuth2AuthorizeReqDTO authzReqDTO)
throws IdentityOAuth2Exception, IdentityOAuthAdminException, InvalidOAuthClientException {
String responseType = authzReqDTO.getResponseType();
OAuth2AuthorizeRespDTO authorizeRespDTO = new OAuth2AuthorizeRespDTO();
if (!responseHandlers.containsKey(responseType)) {
log.warn("Unsupported Response Type : " + responseType +
" provided for user : " + authzReqDTO.getUser());
handleErrorRequest(authorizeRespDTO, OAuthError.CodeResponse.UNSUPPORTED_RESPONSE_TYPE,
"Unsupported Response Type!");
authorizeRespDTO.setCallbackURI(authzReqDTO.getCallbackUrl());
return authorizeRespDTO;
}
ResponseTypeHandler authzHandler = responseHandlers.get(responseType);
OAuthAuthzReqMessageContext authzReqMsgCtx = new OAuthAuthzReqMessageContext(authzReqDTO);
// loading the stored application data
OAuthAppDO oAuthAppDO = getAppInformation(authzReqDTO);
authzReqMsgCtx.addProperty("OAuthAppDO", oAuthAppDO);
boolean accessDelegationAuthzStatus = authzHandler.validateAccessDelegation(authzReqMsgCtx);
if(authzReqMsgCtx.getProperty("ErrorCode") != null){
authorizeRespDTO.setErrorCode((String)authzReqMsgCtx.getProperty("ErrorCode"));
authorizeRespDTO.setErrorMsg((String)authzReqMsgCtx.getProperty("ErrorMsg"));
authorizeRespDTO.setCallbackURI(authzReqDTO.getCallbackUrl());
return authorizeRespDTO;
} else if (!accessDelegationAuthzStatus) {
log.warn("User : " + authzReqDTO.getUser() +
" doesn't have necessary rights to grant access to the resource(s) " +
OAuth2Util.buildScopeString(authzReqDTO.getScopes()));
handleErrorRequest(authorizeRespDTO, OAuthError.CodeResponse.UNAUTHORIZED_CLIENT,
"Authorization Failure!");
authorizeRespDTO.setCallbackURI(authzReqDTO.getCallbackUrl());
return authorizeRespDTO;
}
boolean scopeValidationStatus = authzHandler.validateScope(authzReqMsgCtx);
if (!scopeValidationStatus) {
log.warn("Scope validation failed for user : "
+ authzReqDTO.getUser() + ", for the scope : "
+ OAuth2Util.buildScopeString(authzReqDTO.getScopes()));
handleErrorRequest(authorizeRespDTO,
OAuthError.CodeResponse.INVALID_SCOPE, "Invalid Scope!");
authorizeRespDTO.setCallbackURI(authzReqDTO.getCallbackUrl());
return authorizeRespDTO;
} else {
// We are here because the call-back handler has approved the scope.
// If call-back handler set the approved scope - then we respect that. If not we take
// the approved scope as the provided scope.
if (authzReqMsgCtx.getApprovedScope() == null
|| authzReqMsgCtx.getApprovedScope().length == 0) {
authzReqMsgCtx
.setApprovedScope(authzReqMsgCtx.getAuthorizationReqDTO().getScopes());
}
}
try {
// set the authorization request context to be used by downstream handlers. This is introduced as a fix for
// IDENTITY-4111
OAuth2Util.setAuthzRequestContext(authzReqMsgCtx);
authorizeRespDTO = authzHandler.issue(authzReqMsgCtx);
} finally {
// clears authorization request context
OAuth2Util.clearAuthzRequestContext();
}
return authorizeRespDTO;
}
private OAuthAppDO getAppInformation(OAuth2AuthorizeReqDTO authzReqDTO) throws IdentityOAuth2Exception,
InvalidOAuthClientException {
OAuthAppDO oAuthAppDO = appInfoCache.getValueFromCache(authzReqDTO.getConsumerKey());
if (oAuthAppDO != null) {
return oAuthAppDO;
} else {
oAuthAppDO = new OAuthAppDAO().getAppInformation(authzReqDTO.getConsumerKey());
appInfoCache.addToCache(authzReqDTO.getConsumerKey(), oAuthAppDO);
return oAuthAppDO;
}
}
private void handleErrorRequest(OAuth2AuthorizeRespDTO respDTO, String errorCode,
String errorMsg) {
respDTO.setErrorCode(errorCode);
respDTO.setErrorMsg(errorMsg);
}
}