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 private static final long serialVersionUID = -5367937758427680765L; 101 102 103 /** 104 * The client authentication requirement for this grant type. 105 */ 106 private final boolean requiresClientAuth; 107 108 109 /** 110 * The client identifier requirement for this grant type. 111 */ 112 private final boolean requiresClientID; 113 114 115 /** 116 * The names of the token request parameters specific to this grant 117 * type. 118 */ 119 private final Set<String> requestParamNames; 120 121 122 /** 123 * Creates a new OAuth 2.0 authorisation grant type with the specified 124 * value. The client authentication requirement is set to 125 * {@code false}. So is the client identifier requirement. 126 * 127 * @param value The authorisation grant type value. Must not be 128 * {@code null} or empty string. 129 */ 130 public GrantType(final String value) { 131 132 this(value, false, false, Collections.<String>emptySet()); 133 } 134 135 136 /** 137 * Creates a new OAuth 2.0 authorisation grant type with the specified 138 * value. 139 * 140 * @param value The authorisation grant type value. Must 141 * not be {@code null} or empty string. 142 * @param requiresClientAuth The client authentication requirement. 143 * @param requiresClientID The client identifier requirement. 144 * @param requestParamNames The names of the token request parameters 145 * specific to this grant type, empty set or 146 * {@code null} if none. 147 */ 148 private GrantType(final String value, 149 final boolean requiresClientAuth, 150 final boolean requiresClientID, 151 final Set<String> requestParamNames) { 152 153 super(value); 154 this.requiresClientAuth = requiresClientAuth; 155 this.requiresClientID = requiresClientID; 156 this.requestParamNames = requestParamNames == null ? Collections.<String>emptySet() : Collections.unmodifiableSet(requestParamNames); 157 } 158 159 160 /** 161 * Gets the client authentication requirement. 162 * 163 * @return {@code true} if explicit client authentication is always 164 * required for this grant type, else {@code false}. 165 */ 166 public boolean requiresClientAuthentication() { 167 168 return requiresClientAuth; 169 } 170 171 172 /** 173 * Gets the client identifier requirement. 174 * 175 * @return {@code true} if a client identifier must always be 176 * communicated for this grant type (either as part of the 177 * client authentication, or as a parameter in the token 178 * request body), else {@code false}. 179 */ 180 public boolean requiresClientID() { 181 182 return requiresClientID; 183 } 184 185 186 /** 187 * Gets the names of the token request parameters specific to this 188 * grant type. 189 * 190 * @return The parameter names, empty set if none. 191 */ 192 public Set<String> getRequestParameterNames() { 193 194 return requestParamNames; 195 } 196 197 198 @Override 199 public boolean equals(final Object object) { 200 201 return object instanceof GrantType && this.toString().equals(object.toString()); 202 } 203 204 205 /** 206 * Parses a grant type from the specified string. 207 * 208 * @param value The string to parse. 209 * 210 * @return The grant type. 211 * 212 * @throws ParseException If string is {@code null}, blank or empty. 213 */ 214 public static GrantType parse(final String value) 215 throws ParseException { 216 217 GrantType grantType; 218 219 try { 220 grantType = new GrantType(value); 221 222 } catch (IllegalArgumentException e) { 223 224 throw new ParseException(e.getMessage()); 225 } 226 227 if (grantType.equals(GrantType.AUTHORIZATION_CODE)) { 228 229 return GrantType.AUTHORIZATION_CODE; 230 231 } else if (grantType.equals(GrantType.IMPLICIT)) { 232 233 return GrantType.IMPLICIT; 234 235 } else if (grantType.equals(GrantType.REFRESH_TOKEN)) { 236 237 return GrantType.REFRESH_TOKEN; 238 239 } else if (grantType.equals(GrantType.PASSWORD)) { 240 241 return GrantType.PASSWORD; 242 243 } else if (grantType.equals(GrantType.CLIENT_CREDENTIALS)) { 244 245 return GrantType.CLIENT_CREDENTIALS; 246 247 } else if (grantType.equals(GrantType.JWT_BEARER)) { 248 249 return GrantType.JWT_BEARER; 250 251 } else if (grantType.equals(GrantType.SAML2_BEARER)) { 252 253 return GrantType.SAML2_BEARER; 254 255 } else if (grantType.equals(GrantType.DEVICE_CODE)) { 256 257 return GrantType.DEVICE_CODE; 258 259 } else if (grantType.equals(GrantType.CIBA)) { 260 261 return GrantType.CIBA; 262 263 } else { 264 265 return grantType; 266 } 267 } 268 269 270 /** 271 * Ensures the specified grant type is set in a list of parameters. 272 * 273 * @param grantType The grant type. Must not be {@code null}. 274 * @param params The parameters. Must not be {@code null}. 275 * 276 * @throws ParseException If the grant type is not set. 277 */ 278 public static void ensure(final GrantType grantType, final Map<String, List<String>> params) 279 throws ParseException { 280 281 // Parse grant type 282 String grantTypeString = MultivaluedMapUtils.getFirstValue(params, "grant_type"); 283 284 if (grantTypeString == null) { 285 String msg = "Missing grant_type parameter"; 286 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg)); 287 } 288 289 if (! GrantType.parse(grantTypeString).equals(grantType)) { 290 String msg = "The grant_type must be " + grantType + ""; 291 throw new ParseException(msg, OAuth2Error.UNSUPPORTED_GRANT_TYPE.appendDescription(": " + msg)); 292 } 293 } 294}