forked from spring-projects/spring-authorization-server
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add client_credentials grant type support
Closes spring-projectsgh-51
- Loading branch information
Showing
12 changed files
with
743 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
85 changes: 85 additions & 0 deletions
85
...h2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/* | ||
* Copyright 2020 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.server.authorization.authentication; | ||
|
||
import java.time.Instant; | ||
import java.time.temporal.ChronoUnit; | ||
import java.util.Base64; | ||
import java.util.Set; | ||
|
||
import org.springframework.security.authentication.AuthenticationProvider; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.core.AuthenticationException; | ||
import org.springframework.security.crypto.keygen.Base64StringKeyGenerator; | ||
import org.springframework.security.crypto.keygen.StringKeyGenerator; | ||
import org.springframework.security.oauth2.core.OAuth2AccessToken; | ||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException; | ||
import org.springframework.security.oauth2.core.OAuth2Error; | ||
import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | ||
|
||
/** | ||
* An {@link AuthenticationProvider} implementation for the OAuth 2.0 Client Credentials Grant. | ||
* | ||
* @author Alexey Nesterov | ||
* @since 0.0.1 | ||
* @see OAuth2ClientCredentialsAuthenticationToken | ||
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-4.4">Section 4.4 Client Credentials Grant</a> | ||
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-4.4.2">Section 4.4.2 Access Token Request</a> | ||
*/ | ||
|
||
public class OAuth2ClientCredentialsAuthenticationProvider implements AuthenticationProvider { | ||
|
||
private final StringKeyGenerator accessTokenGenerator = new Base64StringKeyGenerator(Base64.getUrlEncoder()); | ||
|
||
@Override | ||
public Authentication authenticate(Authentication authentication) throws AuthenticationException { | ||
OAuth2ClientCredentialsAuthenticationToken clientCredentialsAuthenticationToken = | ||
(OAuth2ClientCredentialsAuthenticationToken) authentication; | ||
|
||
OAuth2ClientAuthenticationToken clientPrincipal = null; | ||
if (OAuth2ClientAuthenticationToken.class.isAssignableFrom(clientCredentialsAuthenticationToken.getPrincipal().getClass())) { | ||
clientPrincipal = (OAuth2ClientAuthenticationToken) clientCredentialsAuthenticationToken.getPrincipal(); | ||
} | ||
|
||
if (clientPrincipal == null || !clientPrincipal.isAuthenticated()) { | ||
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_CLIENT)); | ||
} | ||
|
||
Set<String> clientScopes = clientPrincipal.getRegisteredClient().getScopes(); | ||
Set<String> requestedScopes = clientCredentialsAuthenticationToken.getScopes(); | ||
if (!clientScopes.containsAll(requestedScopes)) { | ||
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_SCOPE)); | ||
} | ||
|
||
if (requestedScopes == null || requestedScopes.isEmpty()) { | ||
requestedScopes = clientScopes; | ||
} | ||
|
||
String tokenValue = this.accessTokenGenerator.generateKey(); | ||
Instant issuedAt = Instant.now(); | ||
Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS); // TODO Allow configuration for access token lifespan | ||
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, | ||
tokenValue, issuedAt, expiresAt, requestedScopes); | ||
|
||
return new OAuth2AccessTokenAuthenticationToken( | ||
clientPrincipal.getRegisteredClient(), clientPrincipal, accessToken); | ||
} | ||
|
||
@Override | ||
public boolean supports(Class<?> authentication) { | ||
return OAuth2ClientCredentialsAuthenticationToken.class.isAssignableFrom(authentication); | ||
} | ||
} |
68 changes: 68 additions & 0 deletions
68
...auth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationToken.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/* | ||
* Copyright 2020 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.server.authorization.authentication; | ||
|
||
import java.util.Collections; | ||
import java.util.Set; | ||
|
||
import org.springframework.security.authentication.AbstractAuthenticationToken; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.oauth2.server.authorization.Version; | ||
import org.springframework.util.Assert; | ||
|
||
/** | ||
* An {@link Authentication} implementation used for the OAuth 2.0 Client Credentials Grant. | ||
* | ||
* @author Alexey Nesterov | ||
* @since 0.0.1 | ||
* @see Authentication | ||
* @see OAuth2ClientCredentialsAuthenticationProvider | ||
*/ | ||
public class OAuth2ClientCredentialsAuthenticationToken extends AbstractAuthenticationToken { | ||
|
||
private static final long serialVersionUID = Version.SERIAL_VERSION_UID; | ||
|
||
private final Authentication clientPrincipal; | ||
private final Set<String> scopes; | ||
|
||
public OAuth2ClientCredentialsAuthenticationToken(Authentication clientPrincipal, Set<String> scopes) { | ||
super(Collections.emptyList()); | ||
Assert.notNull(clientPrincipal, "clientPrincipal cannot be null"); | ||
Assert.notNull(scopes, "scopes cannot be null"); | ||
this.clientPrincipal = clientPrincipal; | ||
this.scopes = scopes; | ||
} | ||
|
||
@SuppressWarnings("unchecked") | ||
public OAuth2ClientCredentialsAuthenticationToken(OAuth2ClientAuthenticationToken clientPrincipal) { | ||
this(clientPrincipal, Collections.EMPTY_SET); | ||
} | ||
|
||
@Override | ||
public Object getCredentials() { | ||
return ""; | ||
} | ||
|
||
@Override | ||
public Object getPrincipal() { | ||
return this.clientPrincipal; | ||
} | ||
|
||
public Set<String> getScopes() { | ||
return this.scopes; | ||
} | ||
} |
61 changes: 61 additions & 0 deletions
61
.../oauth2/server/authorization/web/DelegatingAuthorizationGrantAuthenticationConverter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* | ||
* Copyright 2020 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.server.authorization.web; | ||
|
||
import javax.servlet.http.HttpServletRequest; | ||
import java.util.Collections; | ||
import java.util.Map; | ||
|
||
import org.springframework.core.convert.converter.Converter; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.oauth2.core.AuthorizationGrantType; | ||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; | ||
import org.springframework.util.Assert; | ||
import org.springframework.util.StringUtils; | ||
|
||
/** | ||
* A {@link Converter} that delegates actual conversion to one of the provided converters based on grant_type param of a request. | ||
* Returns null is grant type is not specified or not supported. | ||
* | ||
* @author Alexey Nesterov | ||
* @since 0.0.1 | ||
*/ | ||
public final class DelegatingAuthorizationGrantAuthenticationConverter implements Converter<HttpServletRequest, Authentication> { | ||
|
||
private final Map<AuthorizationGrantType, Converter<HttpServletRequest, Authentication>> converters; | ||
|
||
public DelegatingAuthorizationGrantAuthenticationConverter(Map<AuthorizationGrantType, Converter<HttpServletRequest, Authentication>> converters) { | ||
Assert.notEmpty(converters, "converters cannot be empty"); | ||
|
||
this.converters = Collections.unmodifiableMap(converters); | ||
} | ||
|
||
@Override | ||
public Authentication convert(HttpServletRequest request) { | ||
String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE); | ||
if (StringUtils.isEmpty(grantType)) { | ||
return null; | ||
} | ||
|
||
Converter<HttpServletRequest, Authentication> converter = this.converters.get(new AuthorizationGrantType(grantType)); | ||
if (converter == null) { | ||
return null; | ||
} | ||
|
||
return converter.convert(request); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.