AuthorizationEndpoint.java 6.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
/*
 * Copyright (c) 2020-2040, 北京符节科技有限公司 (support@fujieid.com & https://www.fujieid.com).
 * <p>
 * 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
 * <p>
 * http://www.gnu.org/licenses/lgpl.html
 * <p>
 * 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);

    /**
智布道's avatar
智布道 已提交
51
     * Authorize current HTTP request
52 53 54
     * <p>
     * When logged in, the method returns the callback url (with parameters such as code)
     * <p>
智布道's avatar
智布道 已提交
55
     * When not logged in, the method returns the login url (with the parameters of the current HTTP request)
56
     *
智布道's avatar
智布道 已提交
57
     * @param request current HTTP request
58 59 60
     * @return Callback url or authorization url
     * @throws IOException IOException
     */
61
    public IdsResponse<String, String> authorize(HttpServletRequest request) throws IOException {
62 63 64 65 66 67 68 69 70 71 72 73
        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);
74
            return new IdsResponse<String, String>().data(url);
75 76
        }

77
        return new IdsResponse<String, String>()
78
            .data(OauthUtil.createAuthorizeUrl(JapIds.getIdsConfig().getLoginPageUrl(), param));
79 80 81 82 83
    }

    /**
     * User-initiated consent authorization
     *
智布道's avatar
智布道 已提交
84
     * @param request current HTTP request
85 86
     * @return Return the callback url (with parameters such as code)
     */
87
    public IdsResponse<String, String> agree(HttpServletRequest request) {
88 89
        IdsRequestParam param = IdsRequestParamProvider.parseRequest(request);

智布道's avatar
智布道 已提交
90
        // The scope checked by the user may be inconsistent with the scope passed in the current HTTP request
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
        String[] requestScopes = request.getParameterValues("scopes");
        Set<String> 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);
110
        return new IdsResponse<String, String>().data(url);
111 112 113 114 115
    }

    /**
     * Generate callback url
     *
智布道's avatar
智布道 已提交
116
     * @param param        Parameters in the current HTTP request
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
     * @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);
    }

}