/* * Copyright (c) 2020-2040, 北京符节科技有限公司 (support@fujieid.com & https://www.fujieid.com). *

* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *

* http://www.gnu.org/licenses/lgpl.html *

* 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 com.fujieid.jap.ids.endpoint; import cn.hutool.core.util.ArrayUtil; import com.fujieid.jap.ids.JapIds; import com.fujieid.jap.ids.exception.InvalidScopeException; import com.fujieid.jap.ids.model.ClientDetail; import com.fujieid.jap.ids.model.IdsRequestParam; import com.fujieid.jap.ids.model.IdsResponse; import com.fujieid.jap.ids.model.UserInfo; import com.fujieid.jap.ids.model.enums.ErrorResponse; import com.fujieid.jap.ids.model.enums.ResponseType; import com.fujieid.jap.ids.provider.IdsAuthorizationProvider; import com.fujieid.jap.ids.provider.IdsRequestParamProvider; import com.fujieid.jap.ids.util.OauthUtil; import com.xkcoding.json.util.StringUtil; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.Arrays; import java.util.Set; import java.util.TreeSet; import java.util.stream.Collectors; /** * Authorization endpoint * * @author yadong.zhang (yadong.zhang0415(a)gmail.com) * @version 1.0.0 * @since 1.0.0 */ public class AuthorizationEndpoint extends AbstractEndpoint { private final IdsAuthorizationProvider idsAuthorizationProvider = new IdsAuthorizationProvider(oauth2Service); /** * Authorize current HTTP request *

* When logged in, the method returns the callback url (with parameters such as code) *

* When not logged in, the method returns the login url (with the parameters of the current HTTP request) * * @param request current HTTP request * @return Callback url or authorization url * @throws IOException IOException */ public IdsResponse authorize(HttpServletRequest request) throws IOException { IdsRequestParam param = IdsRequestParamProvider.parseRequest(request); ClientDetail clientDetail = JapIds.getContext().getClientDetailService().getByClientId(param.getClientId()); OauthUtil.validClientDetail(clientDetail); OauthUtil.validateResponseType(param.getResponseType(), clientDetail.getResponseTypes()); OauthUtil.validateRedirectUri(param.getRedirectUri(), clientDetail); OauthUtil.validateScope(param.getScope(), clientDetail.getScopes()); if (JapIds.isAuthenticated(request)) { UserInfo userInfo = JapIds.getUserInfo(request); String url = generateResponseUrl(param, param.getResponseType(), clientDetail, userInfo); return new IdsResponse().data(url); } return new IdsResponse() .data(OauthUtil.createAuthorizeUrl(JapIds.getIdsConfig().getLoginPageUrl(), param)); } /** * User-initiated consent authorization * * @param request current HTTP request * @return Return the callback url (with parameters such as code) */ public IdsResponse agree(HttpServletRequest request) { IdsRequestParam param = IdsRequestParamProvider.parseRequest(request); // The scope checked by the user may be inconsistent with the scope passed in the current HTTP request String[] requestScopes = request.getParameterValues("scopes"); Set scopes = null; if (ArrayUtil.isEmpty(requestScopes)) { if (StringUtil.isEmpty(param.getScope())) { throw new InvalidScopeException(ErrorResponse.INVALID_SCOPE); } scopes = OauthUtil.convertStrToList(param.getScope()).stream().distinct().collect(Collectors.toSet()); } else { scopes = new TreeSet<>(Arrays.asList(requestScopes)); } // Ultimately participating in the authorized scope param.setScope(String.join(" ", scopes)); ClientDetail clientDetail = JapIds.getContext().getClientDetailService().getByClientId(param.getClientId()); OauthUtil.validClientDetail(clientDetail); String responseType = param.getResponseType(); UserInfo userInfo = JapIds.getUserInfo(request); String url = generateResponseUrl(param, responseType, clientDetail, userInfo); return new IdsResponse().data(url); } /** * Generate callback url * * @param param Parameters in the current HTTP request * @param responseType oauth authorized response type * @param clientDetail Currently authorized client * @return Callback url */ private String generateResponseUrl(IdsRequestParam param, String responseType, ClientDetail clientDetail, UserInfo userInfo) { if (ResponseType.CODE.getType().equalsIgnoreCase(responseType)) { return idsAuthorizationProvider.generateAuthorizationCodeResponse(userInfo, param, clientDetail); } if (ResponseType.TOKEN.getType().equalsIgnoreCase(responseType)) { return idsAuthorizationProvider.generateImplicitGrantResponse(userInfo, param, clientDetail); } if (ResponseType.ID_TOKEN.getType().equalsIgnoreCase(responseType)) { return idsAuthorizationProvider.generateIdTokenAuthorizationResponse(userInfo, param, clientDetail); } if (ResponseType.ID_TOKEN_TOKEN.getType().equalsIgnoreCase(responseType)) { return idsAuthorizationProvider.generateIdTokenTokenAuthorizationResponse(userInfo, param, clientDetail); } if (ResponseType.CODE_ID_TOKEN.getType().equalsIgnoreCase(responseType)) { return idsAuthorizationProvider.generateCodeIdTokenAuthorizationResponse(userInfo, param, clientDetail); } if (ResponseType.CODE_TOKEN.getType().equalsIgnoreCase(responseType)) { return idsAuthorizationProvider.generateCodeTokenAuthorizationResponse(userInfo, param, clientDetail); } if (ResponseType.CODE_ID_TOKEN_TOKEN.getType().equalsIgnoreCase(responseType)) { return idsAuthorizationProvider.generateCodeIdTokenTokenAuthorizationResponse(userInfo, param, clientDetail); } // none return idsAuthorizationProvider.generateNoneAuthorizationResponse(param); } }