001/* 002 * oauth2-oidc-sdk 003 * 004 * Copyright 2012-2021, 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.*; 022 023import net.jcip.annotations.Immutable; 024 025import com.nimbusds.oauth2.sdk.id.Identifier; 026import com.nimbusds.oauth2.sdk.util.MultivaluedMapUtils; 027 028 029/** 030 * Authorisation grant type. 031 */ 032@Immutable 033public final class GrantType extends Identifier { 034 035 036 /** 037 * Authorisation code. Client authentication required only for 038 * confidential clients. 039 */ 040 public static final GrantType AUTHORIZATION_CODE = new GrantType("authorization_code", false, true, new HashSet<>(Arrays.asList("code", "redirect_uri", "code_verifier"))); 041 042 043 /** 044 * Implicit. Client authentication is not performed (except for signed 045 * OpenID Connect authentication requests). 046 */ 047 public static final GrantType IMPLICIT = new GrantType("implicit", false, true, Collections.<String>emptySet()); 048 049 050 /** 051 * Refresh token. Client authentication required only for confidential 052 * clients. 053 */ 054 public static final GrantType REFRESH_TOKEN = new GrantType("refresh_token", false, false, Collections.singleton("refresh_token")); 055 056 057 /** 058 * Password. Client authentication required only for confidential 059 * clients. 060 */ 061 public static final GrantType PASSWORD = new GrantType("password", false, false, new HashSet<>(Arrays.asList("username", "password"))); 062 063 064 /** 065 * Client credentials. Client authentication is required. 066 */ 067 public static final GrantType CLIENT_CREDENTIALS = new GrantType("client_credentials", true, true, Collections.<String>emptySet()); 068 069 070 /** 071 * JWT bearer, as defined in RFC 7523. Explicit client authentication 072 * is optional. 073 */ 074 public static final GrantType JWT_BEARER = new GrantType("urn:ietf:params:oauth:grant-type:jwt-bearer", false, false, Collections.singleton("assertion")); 075 076 077 /** 078 * SAML 2.0 bearer, as defined in RFC 7522. Explicit client 079 * authentication is optional. 080 */ 081 public static final GrantType SAML2_BEARER = new GrantType("urn:ietf:params:oauth:grant-type:saml2-bearer", false, false, Collections.singleton("assertion")); 082 083 084 /** 085 * Device Code, as defined in OAuth 2.0 Device Flow for 086 * Browserless and Input Constrained Devices. Explicit client 087 * authentication is optional. 088 */ 089 public static final GrantType DEVICE_CODE = new GrantType("urn:ietf:params:oauth:grant-type:device_code", false, true, Collections.singleton("device_code")); 090 091 092 /** 093 * Client Initiated Back-channel Authentication (CIBA), as defined in 094 * OpenID Connect Client Initiated Backchannel Authentication Flow - 095 * Core 1.0. Explicit client authentication is optional. 096 */ 097 public static final GrantType CIBA = new GrantType("urn:openid:params:grant-type:ciba", true, true, Collections.singleton("auth_req_id")); 098 099 100 /** 101 * Token Exchange, as defined in RFC 8693. Explicit client 102 * authentication is optional. 103 */ 104 public static final GrantType TOKEN_EXCHANGE = new GrantType("urn:ietf:params:oauth:grant-type:token-exchange", 105 false, false, 106 new HashSet<>(Arrays.asList( 107 "audience", "requested_token_type", "subject_token", "subject_token_type", "actor_token", "actor_token_type" 108 ))); 109 110 111 private static final long serialVersionUID = -5367937758427680765L; 112 113 114 /** 115 * The client authentication requirement for this grant type. 116 */ 117 private final boolean requiresClientAuth; 118 119 120 /** 121 * The client identifier requirement for this grant type. 122 */ 123 private final boolean requiresClientID; 124 125 126 /** 127 * The names of the token request parameters specific to this grant 128 * type. 129 */ 130 private final Set<String> requestParamNames; 131 132 133 /** 134 * Creates a new OAuth 2.0 authorisation grant type with the specified 135 * value. The client authentication requirement is set to 136 * {@code false}. So is the client identifier requirement. 137 * 138 * @param value The authorisation grant type value. Must not be 139 * {@code null} or empty string. 140 */ 141 public GrantType(final String value) { 142 143 this(value, false, false, Collections.<String>emptySet()); 144 } 145 146 147 /** 148 * Creates a new OAuth 2.0 authorisation grant type with the specified 149 * value. 150 * 151 * @param value The authorisation grant type value. Must 152 * not be {@code null} or empty string. 153 * @param requiresClientAuth The client authentication requirement. 154 * @param requiresClientID The client identifier requirement. 155 * @param requestParamNames The names of the token request parameters 156 * specific to this grant type, empty set or 157 * {@code null} if none. 158 */ 159 private GrantType(final String value, 160 final boolean requiresClientAuth, 161 final boolean requiresClientID, 162 final Set<String> requestParamNames) { 163 164 super(value); 165 this.requiresClientAuth = requiresClientAuth; 166 this.requiresClientID = requiresClientID; 167 this.requestParamNames = requestParamNames == null ? Collections.<String>emptySet() : Collections.unmodifiableSet(requestParamNames); 168 } 169 170 171 /** 172 * Gets the client authentication requirement. 173 * 174 * @return {@code true} if explicit client authentication is always 175 * required for this grant type, else {@code false}. 176 */ 177 public boolean requiresClientAuthentication() { 178 179 return requiresClientAuth; 180 } 181 182 183 /** 184 * Gets the client identifier requirement. 185 * 186 * @return {@code true} if a client identifier must always be 187 * communicated for this grant type (either as part of the 188 * client authentication, or as a parameter in the token 189 * request body), else {@code false}. 190 */ 191 public boolean requiresClientID() { 192 193 return requiresClientID; 194 } 195 196 197 /** 198 * Gets the names of the token request parameters specific to this 199 * grant type. 200 * 201 * @return The parameter names, empty set if none. 202 */ 203 public Set<String> getRequestParameterNames() { 204 205 return requestParamNames; 206 } 207 208 209 @Override 210 public boolean equals(final Object object) { 211 212 return object instanceof GrantType && this.toString().equals(object.toString()); 213 } 214 215 216 /** 217 * Parses a grant type from the specified string. 218 * 219 * @param value The string to parse. 220 * 221 * @return The grant type. 222 * 223 * @throws ParseException If string is {@code null}, blank or empty. 224 */ 225 public static GrantType parse(final String value) 226 throws ParseException { 227 228 GrantType grantType; 229 230 try { 231 grantType = new GrantType(value); 232 233 } catch (IllegalArgumentException e) { 234 235 throw new ParseException(e.getMessage()); 236 } 237 238 if (grantType.equals(GrantType.AUTHORIZATION_CODE)) { 239 240 return GrantType.AUTHORIZATION_CODE; 241 242 } else if (grantType.equals(GrantType.IMPLICIT)) { 243 244 return GrantType.IMPLICIT; 245 246 } else if (grantType.equals(GrantType.REFRESH_TOKEN)) { 247 248 return GrantType.REFRESH_TOKEN; 249 250 } else if (grantType.equals(GrantType.PASSWORD)) { 251 252 return GrantType.PASSWORD; 253 254 } else if (grantType.equals(GrantType.CLIENT_CREDENTIALS)) { 255 256 return GrantType.CLIENT_CREDENTIALS; 257 258 } else if (grantType.equals(GrantType.JWT_BEARER)) { 259 260 return GrantType.JWT_BEARER; 261 262 } else if (grantType.equals(GrantType.SAML2_BEARER)) { 263 264 return GrantType.SAML2_BEARER; 265 266 } else if (grantType.equals(GrantType.DEVICE_CODE)) { 267 268 return GrantType.DEVICE_CODE; 269 270 } else if (grantType.equals(GrantType.CIBA)) { 271 272 return GrantType.CIBA; 273 274 } else if (grantType.equals(GrantType.TOKEN_EXCHANGE)) { 275 276 return GrantType.TOKEN_EXCHANGE; 277 278 } else { 279 280 return grantType; 281 } 282 } 283 284 285 /** 286 * Ensures the specified grant type is set in a list of parameters. 287 * 288 * @param grantType The grant type. Must not be {@code null}. 289 * @param params The parameters. Must not be {@code null}. 290 * 291 * @throws ParseException If the grant type is not set. 292 */ 293 public static void ensure(final GrantType grantType, final Map<String, List<String>> params) 294 throws ParseException { 295 296 // Parse grant type 297 String grantTypeString = MultivaluedMapUtils.getFirstValue(params, "grant_type"); 298 299 if (grantTypeString == null) { 300 String msg = "Missing grant_type parameter"; 301 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg)); 302 } 303 304 if (! GrantType.parse(grantTypeString).equals(grantType)) { 305 String msg = "The grant_type must be " + grantType + ""; 306 throw new ParseException(msg, OAuth2Error.UNSUPPORTED_GRANT_TYPE.appendDescription(": " + msg)); 307 } 308 } 309}