@ -16,6 +16,7 @@
@@ -16,6 +16,7 @@
package org.springframework.security.oauth2.core.endpoint ;
import java.io.Serial ;
import java.io.Serializable ;
import java.net.URI ;
import java.nio.charset.StandardCharsets ;
@ -51,31 +52,46 @@ import org.springframework.web.util.UriUtils;
@@ -51,31 +52,46 @@ import org.springframework.web.util.UriUtils;
* "https://tools.ietf.org/html/rfc6749#section-4.1.1" > Section 4 . 1 . 1 Authorization Code
* Grant Request < / a >
* /
public final class OAuth2AuthorizationRequest implements Serializable {
public class OAuth2AuthorizationRequest implements Serializable {
@Serial
private static final long serialVersionUID = 620L ;
private String authorizationUri ;
private final String authorizationUri ;
private AuthorizationGrantType authorizationGrantType ;
private final AuthorizationGrantType authorizationGrantType ;
private OAuth2AuthorizationResponseType responseType ;
private final OAuth2AuthorizationResponseType responseType ;
private String clientId ;
private final String clientId ;
private String redirectUri ;
private final String redirectUri ;
private Set < String > scopes ;
private final Set < String > scopes ;
private String state ;
private final String state ;
private Map < String , Object > additionalParameters ;
private final Map < String , Object > additionalParameters ;
private String authorizationRequestUri ;
private final String authorizationRequestUri ;
private Map < String , Object > attributes ;
private final Map < String , Object > attributes ;
private OAuth2AuthorizationRequest ( ) {
protected OAuth2AuthorizationRequest ( AbstractBuilder < ? , ? > builder ) {
Assert . hasText ( builder . authorizationUri , "authorizationUri cannot be empty" ) ;
Assert . hasText ( builder . clientId , "clientId cannot be empty" ) ;
this . authorizationUri = builder . authorizationUri ;
this . authorizationGrantType = builder . authorizationGrantType ;
this . responseType = builder . responseType ;
this . clientId = builder . clientId ;
this . redirectUri = builder . redirectUri ;
this . scopes = Collections . unmodifiableSet (
CollectionUtils . isEmpty ( builder . scopes ) ? Collections . emptySet ( ) : new LinkedHashSet < > ( builder . scopes ) ) ;
this . state = builder . state ;
this . additionalParameters = Collections . unmodifiableMap ( builder . additionalParameters ) ;
this . authorizationRequestUri = StringUtils . hasText ( builder . authorizationRequestUri )
? builder . authorizationRequestUri : builder . buildAuthorizationRequestUri ( ) ;
this . attributes = Collections . unmodifiableMap ( builder . attributes ) ;
}
/ * *
@ -185,7 +201,7 @@ public final class OAuth2AuthorizationRequest implements Serializable {
@@ -185,7 +201,7 @@ public final class OAuth2AuthorizationRequest implements Serializable {
* @return the { @link Builder }
* /
public static Builder authorizationCode ( ) {
return new Builder ( AuthorizationGrantType . AUTHORIZATION_CODE ) ;
return new Builder ( ) ;
}
@Override
@ -226,7 +242,7 @@ public final class OAuth2AuthorizationRequest implements Serializable {
@@ -226,7 +242,7 @@ public final class OAuth2AuthorizationRequest implements Serializable {
public static Builder from ( OAuth2AuthorizationRequest authorizationRequest ) {
Assert . notNull ( authorizationRequest , "authorizationRequest cannot be null" ) ;
// @formatter:off
return new Builder ( authorizationRequest . getGrantType ( ) )
return new Builder ( )
. authorizationUri ( authorizationRequest . getAuthorizationUri ( ) )
. clientId ( authorizationRequest . getClientId ( ) )
. redirectUri ( authorizationRequest . getRedirectUri ( ) )
@ -240,13 +256,32 @@ public final class OAuth2AuthorizationRequest implements Serializable {
@@ -240,13 +256,32 @@ public final class OAuth2AuthorizationRequest implements Serializable {
/ * *
* A builder for { @link OAuth2AuthorizationRequest } .
* /
public static final class Builder {
public static class Builder extends AbstractBuilder < OAuth2AuthorizationRequest , Builder > {
/ * *
* Builds a new { @link OAuth2AuthorizationRequest } .
* @return a { @link OAuth2AuthorizationRequest }
* /
@Override
public OAuth2AuthorizationRequest build ( ) {
return new OAuth2AuthorizationRequest ( this ) ;
}
}
/ * *
* A builder for subclasses of { @link OAuth2AuthorizationRequest } .
*
* @param < T > the type of authorization request
* @param < B > the type of the builder
* /
protected abstract static class AbstractBuilder < T extends OAuth2AuthorizationRequest , B extends AbstractBuilder < T , B > > {
private String authorizationUri ;
private AuthorizationGrantType authorizationGrantType ;
private final AuthorizationGrantType authorizationGrantType = AuthorizationGrantType . AUTHORIZATION_CODE ;
private OAuth2AuthorizationResponseType responseType ;
private final OAuth2AuthorizationResponseType responseType = OAuth2AuthorizationResponseType . CODE ;
private String clientId ;
@ -269,12 +304,7 @@ public final class OAuth2AuthorizationRequest implements Serializable {
@@ -269,12 +304,7 @@ public final class OAuth2AuthorizationRequest implements Serializable {
private final DefaultUriBuilderFactory uriBuilderFactory ;
private Builder ( AuthorizationGrantType authorizationGrantType ) {
Assert . notNull ( authorizationGrantType , "authorizationGrantType cannot be null" ) ;
this . authorizationGrantType = authorizationGrantType ;
if ( AuthorizationGrantType . AUTHORIZATION_CODE . equals ( authorizationGrantType ) ) {
this . responseType = OAuth2AuthorizationResponseType . CODE ;
}
protected AbstractBuilder ( ) {
this . uriBuilderFactory = new DefaultUriBuilderFactory ( ) ;
// The supplied authorizationUri may contain encoded parameters
// so disable encoding in UriBuilder and instead apply encoding within this
@ -282,78 +312,85 @@ public final class OAuth2AuthorizationRequest implements Serializable {
@@ -282,78 +312,85 @@ public final class OAuth2AuthorizationRequest implements Serializable {
this . uriBuilderFactory . setEncodingMode ( DefaultUriBuilderFactory . EncodingMode . NONE ) ;
}
@SuppressWarnings ( "unchecked" )
protected final B getThis ( ) {
// avoid unchecked casts in subclasses by using "getThis()" instead of "(B)
// this"
return ( B ) this ;
}
/ * *
* Sets the uri for the authorization endpoint .
* @param authorizationUri the uri for the authorization endpoint
* @return the { @link Builder }
* @return the { @link Abstract Builder}
* /
public Builder authorizationUri ( String authorizationUri ) {
public B authorizationUri ( String authorizationUri ) {
this . authorizationUri = authorizationUri ;
return this ;
return getThis ( ) ;
}
/ * *
* Sets the client identifier .
* @param clientId the client identifier
* @return the { @link Builder }
* @return the { @link Abstract Builder}
* /
public Builder clientId ( String clientId ) {
public B clientId ( String clientId ) {
this . clientId = clientId ;
return this ;
return getThis ( ) ;
}
/ * *
* Sets the uri for the redirection endpoint .
* @param redirectUri the uri for the redirection endpoint
* @return the { @link Builder }
* @return the { @link Abstract Builder}
* /
public Builder redirectUri ( String redirectUri ) {
public B redirectUri ( String redirectUri ) {
this . redirectUri = redirectUri ;
return this ;
return getThis ( ) ;
}
/ * *
* Sets the scope ( s ) .
* @param scope the scope ( s )
* @return the { @link Builder }
* @return the { @link Abstract Builder}
* /
public Builder scope ( String . . . scope ) {
public B scope ( String . . . scope ) {
if ( scope ! = null & & scope . length > 0 ) {
return scopes ( new LinkedHashSet < > ( Arrays . asList ( scope ) ) ) ;
}
return this ;
return getThis ( ) ;
}
/ * *
* Sets the scope ( s ) .
* @param scopes the scope ( s )
* @return the { @link Builder }
* @return the { @link Abstract Builder}
* /
public Builder scopes ( Set < String > scopes ) {
public B scopes ( Set < String > scopes ) {
this . scopes = scopes ;
return this ;
return getThis ( ) ;
}
/ * *
* Sets the state .
* @param state the state
* @return the { @link Builder }
* @return the { @link Abstract Builder}
* /
public Builder state ( String state ) {
public B state ( String state ) {
this . state = state ;
return this ;
return getThis ( ) ;
}
/ * *
* Sets the additional parameter ( s ) used in the request .
* @param additionalParameters the additional parameter ( s ) used in the request
* @return the { @link Builder }
* @return the { @link Abstract Builder}
* /
public Builder additionalParameters ( Map < String , Object > additionalParameters ) {
public B additionalParameters ( Map < String , Object > additionalParameters ) {
if ( ! CollectionUtils . isEmpty ( additionalParameters ) ) {
this . additionalParameters . putAll ( additionalParameters ) ;
}
return this ;
return getThis ( ) ;
}
/ * *
@ -361,52 +398,55 @@ public final class OAuth2AuthorizationRequest implements Serializable {
@@ -361,52 +398,55 @@ public final class OAuth2AuthorizationRequest implements Serializable {
* allowing the ability to add , replace , or remove .
* @param additionalParametersConsumer a { @code Consumer } of the additional
* parameters
* @return the { @link AbstractBuilder }
* @since 5 . 3
* /
public Builder additionalParameters ( Consumer < Map < String , Object > > additionalParametersConsumer ) {
public B additionalParameters ( Consumer < Map < String , Object > > additionalParametersConsumer ) {
if ( additionalParametersConsumer ! = null ) {
additionalParametersConsumer . accept ( this . additionalParameters ) ;
}
return this ;
return getThis ( ) ;
}
/ * *
* A { @code Consumer } to be provided access to all the parameters allowing the
* ability to add , replace , or remove .
* @param parametersConsumer a { @code Consumer } of all the parameters
* @return the { @link AbstractBuilder }
* @since 5 . 3
* /
public Builder parameters ( Consumer < Map < String , Object > > parametersConsumer ) {
public B parameters ( Consumer < Map < String , Object > > parametersConsumer ) {
if ( parametersConsumer ! = null ) {
this . parametersConsumer = parametersConsumer ;
}
return this ;
return getThis ( ) ;
}
/ * *
* Sets the attributes associated to the request .
* @param attributes the attributes associated to the request
* @return the { @link Builder }
* @return the { @link Abstract Builder}
* @since 5 . 2
* /
public Builder attributes ( Map < String , Object > attributes ) {
public B attributes ( Map < String , Object > attributes ) {
if ( ! CollectionUtils . isEmpty ( attributes ) ) {
this . attributes . putAll ( attributes ) ;
}
return this ;
return getThis ( ) ;
}
/ * *
* A { @code Consumer } to be provided access to the attribute ( s ) allowing the
* ability to add , replace , or remove .
* @param attributesConsumer a { @code Consumer } of the attribute ( s )
* @return the { @link AbstractBuilder }
* @since 5 . 3
* /
public Builder attributes ( Consumer < Map < String , Object > > attributesConsumer ) {
public B attributes ( Consumer < Map < String , Object > > attributesConsumer ) {
if ( attributesConsumer ! = null ) {
attributesConsumer . accept ( this . attributes ) ;
}
return this ;
return getThis ( ) ;
}
/ * *
@ -418,12 +458,12 @@ public final class OAuth2AuthorizationRequest implements Serializable {
@@ -418,12 +458,12 @@ public final class OAuth2AuthorizationRequest implements Serializable {
* { @code application / x - www - form - urlencoded } MIME format .
* @param authorizationRequestUri the { @code URI } string representation of the
* OAuth 2 . 0 Authorization Request
* @return the { @link Builder }
* @return the { @link Abstract Builder}
* @since 5 . 1
* /
public Builder authorizationRequestUri ( String authorizationRequestUri ) {
public B authorizationRequestUri ( String authorizationRequestUri ) {
this . authorizationRequestUri = authorizationRequestUri ;
return this ;
return getThis ( ) ;
}
/ * *
@ -431,37 +471,17 @@ public final class OAuth2AuthorizationRequest implements Serializable {
@@ -431,37 +471,17 @@ public final class OAuth2AuthorizationRequest implements Serializable {
* OAuth 2 . 0 Authorization Request allowing for further customizations .
* @param authorizationRequestUriFunction a { @code Function } to be provided a
* { @code UriBuilder } representation of the OAuth 2 . 0 Authorization Request
* @return the { @link AbstractBuilder }
* @since 5 . 3
* /
public Builder authorizationRequestUri ( Function < UriBuilder , URI > authorizationRequestUriFunction ) {
public B authorizationRequestUri ( Function < UriBuilder , URI > authorizationRequestUriFunction ) {
if ( authorizationRequestUriFunction ! = null ) {
this . authorizationRequestUriFunction = authorizationRequestUriFunction ;
}
return this ;
return getThis ( ) ;
}
/ * *
* Builds a new { @link OAuth2AuthorizationRequest } .
* @return a { @link OAuth2AuthorizationRequest }
* /
public OAuth2AuthorizationRequest build ( ) {
Assert . hasText ( this . authorizationUri , "authorizationUri cannot be empty" ) ;
Assert . hasText ( this . clientId , "clientId cannot be empty" ) ;
OAuth2AuthorizationRequest authorizationRequest = new OAuth2AuthorizationRequest ( ) ;
authorizationRequest . authorizationUri = this . authorizationUri ;
authorizationRequest . authorizationGrantType = this . authorizationGrantType ;
authorizationRequest . responseType = this . responseType ;
authorizationRequest . clientId = this . clientId ;
authorizationRequest . redirectUri = this . redirectUri ;
authorizationRequest . state = this . state ;
authorizationRequest . scopes = Collections . unmodifiableSet (
CollectionUtils . isEmpty ( this . scopes ) ? Collections . emptySet ( ) : new LinkedHashSet < > ( this . scopes ) ) ;
authorizationRequest . additionalParameters = Collections . unmodifiableMap ( this . additionalParameters ) ;
authorizationRequest . attributes = Collections . unmodifiableMap ( this . attributes ) ;
authorizationRequest . authorizationRequestUri = StringUtils . hasText ( this . authorizationRequestUri )
? this . authorizationRequestUri : this . buildAuthorizationRequestUri ( ) ;
return authorizationRequest ;
}
public abstract T build ( ) ;
private String buildAuthorizationRequestUri ( ) {
Map < String , Object > parameters = getParameters ( ) ; // Not encoded
@ -486,7 +506,7 @@ public final class OAuth2AuthorizationRequest implements Serializable {
@@ -486,7 +506,7 @@ public final class OAuth2AuthorizationRequest implements Serializable {
return this . authorizationRequestUriFunction . apply ( uriBuilder ) . toString ( ) ;
}
private Map < String , Object > getParameters ( ) {
protected Map < String , Object > getParameters ( ) {
Map < String , Object > parameters = new LinkedHashMap < > ( ) ;
parameters . put ( OAuth2ParameterNames . RESPONSE_TYPE , this . responseType . getValue ( ) ) ;
parameters . put ( OAuth2ParameterNames . CLIENT_ID , this . clientId ) ;