001/*
002 * oauth2-oidc-sdk
003 *
004 * Copyright 2012-2016, Connect2id Ltd and contributors.
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
007 * this file except in compliance with the License. You may obtain a copy of the
008 * License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software distributed
013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
015 * specific language governing permissions and limitations under the License.
016 */
017
018package com.nimbusds.oauth2.sdk;
019
020
021import java.util.List;
022import java.util.Map;
023
024import com.nimbusds.oauth2.sdk.device.DeviceCodeGrant;
025import com.nimbusds.oauth2.sdk.util.MultivaluedMapUtils;
026
027
028/**
029 * Authorisation grant. Extending classes should be immutable.
030 *
031 * <p>Supported authorisation grant types:
032 *
033 * <ul>
034 *     <li>{@link GrantType#AUTHORIZATION_CODE Authorisation code}
035 *     <li>{@link GrantType#PASSWORD Resource owner password credentials}
036 *     <li>{@link GrantType#CLIENT_CREDENTIALS Client credentials}
037 *     <li>{@link GrantType#REFRESH_TOKEN Refresh token}
038 *     <li>{@link GrantType#JWT_BEARER}
039 *     <li>{@link GrantType#SAML2_BEARER}
040 *     <li>{@link GrantType#DEVICE_CODE}
041 * </ul>
042 *
043 * <p>Related specifications:
044 *
045 * <ul>
046 *     <li>OAuth 2.0 (RFC 6749), sections 1.3.
047 * </ul>
048 */
049public abstract class AuthorizationGrant {
050
051
052        /**
053         * The authorisation grant type.
054         */
055        private final GrantType type;
056
057
058        /**
059         * Creates a new authorisation grant.
060         *
061         * @param type               The authorisation grant type. Must not be
062         *                           {@code null}.
063         */
064        protected AuthorizationGrant(final GrantType type) {
065
066                if (type == null)
067                        throw new IllegalArgumentException("The grant type must not be null");
068
069                this.type = type;
070        }
071
072
073        /**
074         * Gets the authorisation grant type.
075         *
076         * @return The authorisation grant type.
077         */
078        public GrantType getType() {
079
080                return type;
081        }
082
083
084        /**
085         * Returns the request body parameters for the authorisation grant.
086         *
087         * @return The parameters.
088         */
089        public abstract Map<String,List<String>> toParameters();
090
091
092        /**
093         * Parses an authorisation grant from the specified request body
094         * parameters.
095         *
096         * @param params The request body parameters. Must not be {@code null}.
097         *
098         * @return The authorisation grant.
099         *
100         * @throws ParseException If parsing failed or the grant type is not
101         *                        supported.
102         */
103        public static AuthorizationGrant parse(final Map<String,List<String>> params)
104                throws ParseException {
105
106                // Parse grant type
107                String grantTypeString = MultivaluedMapUtils.getFirstValue(params, "grant_type");
108
109                if (grantTypeString == null) {
110                        String msg = "Missing \"grant_type\" parameter";
111                        throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg));
112                }
113
114                GrantType grantType;
115                try {
116                        grantType = GrantType.parse(grantTypeString);
117                } catch (ParseException e) {
118                        String msg = "Invalid grant type: " + e.getMessage();
119                        throw new ParseException(msg, OAuth2Error.UNSUPPORTED_GRANT_TYPE.appendDescription(": " + msg));
120                }
121
122                if (grantType.equals(GrantType.AUTHORIZATION_CODE)) {
123
124                        return AuthorizationCodeGrant.parse(params);
125
126                } else if (grantType.equals(GrantType.REFRESH_TOKEN)) {
127
128                        return RefreshTokenGrant.parse(params);
129                        
130                } else if (grantType.equals(GrantType.PASSWORD)) {
131
132                        return ResourceOwnerPasswordCredentialsGrant.parse(params);
133
134                } else if (grantType.equals(GrantType.CLIENT_CREDENTIALS)) {
135
136                        return ClientCredentialsGrant.parse(params);
137
138                } else if (grantType.equals(GrantType.JWT_BEARER)) {
139
140                        return JWTBearerGrant.parse(params);
141
142                } else if (grantType.equals(GrantType.SAML2_BEARER)) {
143
144                        return SAML2BearerGrant.parse(params);
145
146                } else if (grantType.equals(GrantType.DEVICE_CODE)) {
147
148                        return DeviceCodeGrant.parse(params);
149
150                } else {
151
152                        throw new ParseException("Invalid or unsupported grant type: " + grantType, OAuth2Error.UNSUPPORTED_GRANT_TYPE);
153                }
154        }
155}