我使用Spring Boot应用程序配置了Hydra实例。我只是使用注释@EnableResourceServer
将我的应用程序配置为资源服务器。因此,当我在请求中使用Bearer授权标头时,Spring使用在属性中指定的值:
security.oauth2.resource.user-info-uri=...
验证令牌是否有效。不幸的是,我找不到Hydra OAuth 2.0的URL(http://docs.hydra13.apiary.io/ / https://github.com/ory/hydra)
最佳答案
首先:在Ory Hydra中配置资源服务器(您必须使用client_credentials和范围'hydra.introspect'将其添加到Ory Hydra中,以便能够请求令牌有效性):
$> hydra clients create --skip-tls-verify \
--id my-rest-api \
--secret mypwd \
--grant-types client_credentials \
--response-types token \
--allowed-scopes hydra.introspect
第二:添加一个策略,让您的资源服务器请求令牌有效性。
$> hydra policies create --skip-tls-verify \
--actions introspect \
--description "Policy to introspect tokens from my api" \
--allow \
--id accesstoken_introsp-policy \
--resources "rn:hydra:oauth2:tokens" \
--subjects my-rest-api
第三:在build.gradle中添加oauth2依赖(如果是maven,则添加pom.xml):
编译
'org.springframework.security.oauth:spring-security-oauth2:2.2.1.RELEASE'
第四:配置application.yml以使用Ory Hydra自省端点获取令牌信息。
security:
user:
password: none
oauth2:
resource:
token-info-uri: https://yourserver.com/oauth2/introspect
client:
client-id: my-rest-api
client-secret: mypwd
scope: [ "hydra.introspect" ]
第五:创建一个类来配置受访问令牌保护的URL
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Autowired
private RemoteTokenServices tokenServices;
@Value("${security.oauth2.client.client-id}")
private String clientId;
@Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.NEVER)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.antMatchers("/api/v1/**").access("#oauth2.hasScope('my.desired.scope')")
.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId(clientId);
tokenServices.setAccessTokenConverter(new OryHydraAccessTokenConverter());
resources.tokenServices(tokenServices);
}
}
class OryHydraAccessTokenConverter extends DefaultAccessTokenConverter {
@Override
public OAuth2Authentication extractAuthentication(Map<String, ?> map) {
OAuth2Authentication oAuth2Authentication = super.extractAuthentication(map);
oAuth2Authentication.setDetails(map.get("ext"));
return oAuth2Authentication;
}
}
我需要一个自定义AccessTokenConverter,因为我的同意应用程序向令牌添加了多个属性,我们需要映射所有属性。使用Ory,我的属性在“ ext”属性下。这是访问令牌的示例:
{
"active": true,
"scope": "my.desired.scope",
"client_id": "my-mobile-app",
"sub": "123121e",
"exp": 1520948372,
"iat": 1520944772,
"iss": "https://yourserver.com",
"ext": {
"custom_prop1": 12321,
"custom_prop2": "Name Surname",
"custom_prop3": false
}
}
最后一步:现在,在控制器中,您可以自动连接为参数Oauth2Authentication对象。
@GetMapping("/api/v1/data")
public MyBean findDataById(OAuth2Authentication auth,
@RequestParam("id") String id) {
OAuth2AuthenticationDetails oAuth2AuthenticationDetails = (OAuth2AuthenticationDetails) auth.getDetails();
Map<String, Object> ext = (Map<String, Object>) oAuth2AuthenticationDetails.getDecodedDetails();
return MyBean.builder().name("Name:"+ext.get("custom_prop1")).build();
}