| 
					
				 | 
			
			
				@@ -0,0 +1,349 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Copyright 2020-2021 the original author or authors. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Licensed under the Apache License, Version 2.0 (the "License"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * you may not use this file except in compliance with the License. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * You may obtain a copy of the License at 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *      https://www.apache.org/licenses/LICENSE-2.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 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 org.springframework.security.oauth2.core.oidc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.security.oauth2.core.AuthorizationGrantType; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.security.oauth2.core.ClientAuthenticationMethod; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.security.oauth2.core.Version; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponseType; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.util.Assert; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.io.Serializable; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.net.URI; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.net.URL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.time.Instant; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.Collections; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.LinkedHashMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.LinkedList; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.List; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.Map; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.function.Consumer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * A representation of an OpenID Client Registration Request and Response, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * which contains a set of claims defined by the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * OpenID Connect Registration 1.0 specification. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @author Ovidiu Popa 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @since 0.1.1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @see OidcClientMetadataClaimAccessor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @see <a href="https://openid.net/specs/openid-connect-registration-1_0.html#ClientRegistration">3.1.  Client Registration Request</a> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+public final class OidcClientRegistration implements OidcClientMetadataClaimAccessor, Serializable { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	private static final long serialVersionUID = Version.SERIAL_VERSION_UID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	private final Map<String, Object> claims; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	private OidcClientRegistration(Map<String, Object> claims) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		this.claims = Collections.unmodifiableMap(claims); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * Returns the OpenID Client Registration metadata. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @return a {@code Map} of the metadata values 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	@Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public Map<String, Object> getClaims() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return this.claims; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * Constructs a new {@link OidcClientRegistration.Builder} with empty claims. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @return the {@link OidcClientRegistration.Builder} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public static Builder builder() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return new Builder(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * Constructs a new {@link Builder} with the provided claims. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param claims the claims to initialize the builder 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public static Builder withClaims(Map<String, Object> claims) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		Assert.notEmpty(claims, "claims cannot be empty"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return new Builder() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				.claims(c -> c.putAll(claims)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public static class Builder { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		private final Map<String, Object> claims = new LinkedHashMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		private Builder() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * Add this Redirect URI to the collection of {@code redirect_uris} in the resulting 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * {@link OidcClientRegistration}, REQUIRED. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @param redirectUri the OAuth 2.0 {@code redirect_uri} value that client supports 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @return the {@link Builder} for further configuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		public Builder redirectUri(String redirectUri) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			addClaimToClaimList(OidcClientMetadataClaimNames.REDIRECT_URIS, redirectUri); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * A {@code Consumer} of the Redirect URI(s) allowing the ability to add, replace, or remove. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @param redirectUriConsumer a {@code Consumer} of the Redirect URI(s) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @return the {@link Builder} for further configuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		public Builder redirectUris(Consumer<List<String>> redirectUriConsumer) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			acceptClaimValues(OidcClientMetadataClaimNames.REDIRECT_URIS, redirectUriConsumer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * Add this Response Type to the collection of {@code response_types} in the resulting 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * {@link OidcClientRegistration}, OPTIONAL. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @param responseType the OAuth 2.0 {@code response_type} value that client supports 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @return the {@link Builder} for further configuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		public Builder responseType(String responseType) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			addClaimToClaimList(OidcClientMetadataClaimNames.RESPONSE_TYPES, responseType); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * Add {@code Consumer}  of {@code response_types} allowing the ability to add, replace, or remove 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * {@link OidcClientRegistration}, OPTIONAL. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @param responseType the OAuth 2.0 {@code response_type} value that client supports 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @return the {@link Builder} for further configuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		public Builder responseTypes(Consumer<List<String>>  responseType) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			acceptClaimValues(OidcClientMetadataClaimNames.RESPONSE_TYPES, responseType); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * Sets {@code client_name} claim in the resulting 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * {@link OidcClientRegistration}, OPTIONAL. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @param clientName the OAuth 2.0 {@code client_name} of the registered client 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @return the {@link Builder} for further configuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		public Builder clientName(String clientName) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return claim(OidcClientMetadataClaimNames.CLIENT_NAME, clientName); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * Sets {@code client_id} claim in the resulting 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * {@link OidcClientRegistration}. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @param clientId the OAuth 2.0 {@code client_id} of the registered client 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @return the {@link Builder} for further configuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		public Builder clientId(String clientId) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return claim(OidcClientMetadataClaimNames.CLIENT_ID, clientId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * Sets {@code client_id_issued_at} claim in the resulting 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * {@link OidcClientRegistration}. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @param clientIssuedAt the timestamp {@code client_id_issued_at} when the client was issued 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @return the {@link Builder} for further configuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		public Builder clientIdIssuedAt(Instant clientIssuedAt) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return claim(OidcClientMetadataClaimNames.CLIENT_ID_ISSUED_AT, clientIssuedAt); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * Sets {@code client_secret} claim in the resulting 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * {@link OidcClientRegistration}. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @param clientSecret the {@code client_secret} of the registered client 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @return the {@link Builder} for further configuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		public Builder clientSecret(String clientSecret) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return claim(OidcClientMetadataClaimNames.CLIENT_SECRET, clientSecret); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * Sets {@code client_secret_expires_at} claim in the resulting 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * {@link OidcClientRegistration}. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @param clientSecretExpiresAt the timestamp {@code client_secret_expires_at} when the client_secret expires 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @return the {@link Builder} for further configuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		public Builder clientSecretExpiresAt(Instant clientSecretExpiresAt) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return claim(OidcClientMetadataClaimNames.CLIENT_SECRET_EXPIRES_AT, clientSecretExpiresAt); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * Add this Grant Type to the collection of {@code grant_types_supported} in the resulting 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * {@link OidcClientRegistration}, OPTIONAL. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @param grantType the OAuth 2.0 {@code grant_type} value that client supports 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @return the {@link Builder} for further configuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		public Builder grantType(String grantType) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			addClaimToClaimList(OidcClientMetadataClaimNames.GRANT_TYPES, grantType); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * A {@code Consumer} of the Grant Type(s) allowing the ability to add, replace, or remove. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @param grantTypesConsumer a {@code Consumer} of the Grant Type(s) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @return the {@link Builder} for further configuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		public Builder grantTypes(Consumer<List<String>> grantTypesConsumer) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			acceptClaimValues(OidcClientMetadataClaimNames.GRANT_TYPES, grantTypesConsumer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * Add this Scope to the collection of {@code scopes_supported} in the resulting 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * {@link OidcClientRegistration}, RECOMMENDED. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @param scope the OAuth 2.0 {@code scope} value that client supports 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @return the {@link Builder} for further configuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		public Builder scope(String scope) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			claim(OidcClientMetadataClaimNames.SCOPE, scope); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * Add {@code Consumer}  of {@code scopes} allowing the ability to add, replace, or remove 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * {@link OidcClientRegistration}, RECOMMENDED. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @param scopesConsumer the OAuth 2.0 {@code scope} value that client supports 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @return the {@link Builder} for further configuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		public Builder scopes(Consumer<List<String>>  scopesConsumer) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			acceptClaimValues(OidcClientMetadataClaimNames.SCOPE, scopesConsumer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * Add this Token endpoint authentication method to the collection of {@code token_endpoint_auth_method} in the resulting 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * {@link OidcClientRegistration}, OPTIONAL. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @param tokenEndpointAuthenticationMethod the OAuth 2.0 {@code token_endpoint_auth_method} value that client supports 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @return the {@link Builder} for further configuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		public Builder tokenEndpointAuthenticationMethod(String tokenEndpointAuthenticationMethod) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			claim(OidcClientMetadataClaimNames.TOKEN_ENDPOINT_AUTH_METHOD, tokenEndpointAuthenticationMethod); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * Add this claim in the resulting {@link OidcClientRegistration}. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @param name  the claim name 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @param value the claim value 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @return the {@link Builder} for further configuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		public Builder claim(String name, Object value) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Assert.hasText(name, "name cannot be empty"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Assert.notNull(value, "value cannot be null"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.claims.put(name, value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * Provides access to every {@link #claim(String, Object)} declared so far with 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * the possibility to add, replace, or remove. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @param claimsConsumer a {@code Consumer} of the claims 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * @return the {@link Builder} for further configurations 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		public Builder claims(Consumer<Map<String, Object>> claimsConsumer) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			claimsConsumer.accept(this.claims); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		public OidcClientRegistration build() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.claims.computeIfAbsent(OidcClientMetadataClaimNames.TOKEN_ENDPOINT_AUTH_METHOD, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					k -> ClientAuthenticationMethod.BASIC.getValue()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// If omitted, the default is that the Client will use only the authorization_code Grant Type. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.claims.computeIfAbsent(OidcClientMetadataClaimNames.GRANT_TYPES, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					k -> Collections.singletonList(AuthorizationGrantType.AUTHORIZATION_CODE.getValue())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			//If omitted, the default is that the Client will use only the code Response Type. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.claims.computeIfAbsent(OidcClientMetadataClaimNames.RESPONSE_TYPES, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					k -> Collections.singletonList(OAuth2AuthorizationResponseType.CODE.getValue())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			validateRedirectUris(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			validateReponseTypesClaim(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			validateGrantTypesClaim(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return new OidcClientRegistration(this.claims); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		private void validateRedirectUris() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// redirect_uris is required 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Assert.notNull(this.claims.get(OidcClientMetadataClaimNames.REDIRECT_URIS), "redirect_uris cannot be null"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Assert.isInstanceOf(List.class, this.claims.get(OidcClientMetadataClaimNames.REDIRECT_URIS), "redirect_uris must be of type list"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Assert.notEmpty((List<?>) this.claims.get(OidcClientMetadataClaimNames.REDIRECT_URIS), "redirect_uris must not be empty"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			((List<?>) this.claims.get(OidcClientMetadataClaimNames.REDIRECT_URIS)).forEach( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					url -> validateURL(url, "redirect_uri must be a valid URL") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		private void validateGrantTypesClaim() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Assert.isInstanceOf(List.class, this.claims.get(OidcClientMetadataClaimNames.GRANT_TYPES), "grant_types must be of type List"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			List<?> grantTypes = (List<?>) this.claims.get(OidcClientMetadataClaimNames.GRANT_TYPES); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// If empty, the default is that the Client will use only the authorization_code Grant Type. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if (grantTypes.isEmpty()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.claims.put(OidcClientMetadataClaimNames.GRANT_TYPES, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						Collections.singletonList(AuthorizationGrantType.AUTHORIZATION_CODE.getValue())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		private void validateReponseTypesClaim() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Assert.isInstanceOf(List.class, this.claims.get(OidcClientMetadataClaimNames.RESPONSE_TYPES), "response_types must be of type List"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			List<?> responseTypes = (List<?>) this.claims.get(OidcClientMetadataClaimNames.RESPONSE_TYPES); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			//If empty, the default is that the Client will use only the code Response Type. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if (responseTypes.isEmpty()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.claims.put(OidcClientMetadataClaimNames.RESPONSE_TYPES, Collections.singletonList(OAuth2AuthorizationResponseType.CODE.getValue())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		private static void validateURL(Object url, String errorMessage) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if (URL.class.isAssignableFrom(url.getClass())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				new URI(url.toString()).toURL(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} catch (Exception ex) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				throw new IllegalArgumentException(errorMessage, ex); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		@SuppressWarnings("unchecked") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		private void addClaimToClaimList(String name, String value) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Assert.hasText(name, "name cannot be empty"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Assert.notNull(value, "value cannot be null"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.claims.computeIfAbsent(name, k -> new LinkedList<String>()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			((List<String>) this.claims.get(name)).add(value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		@SuppressWarnings("unchecked") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		private void acceptClaimValues(String name, Consumer<List<String>> valuesConsumer) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Assert.hasText(name, "name cannot be empty"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Assert.notNull(valuesConsumer, "valuesConsumer cannot be null"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.claims.computeIfAbsent(name, k -> new LinkedList<String>()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			List<String> values = (List<String>) this.claims.get(name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			valuesConsumer.accept(values); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |