问题
I have a spring boot application which is using Oauth with OneLogin as the authorisation server. Now, I want to implement role based authorisation to expose certain APIs only to users with certain privileges.
I have users belonging to groups. Say user A belongs to "admin" group and user B does not belong to the admin group. My question is how can I use these groups to enable only user A to access certain APIs.
This is the information about the authenticated user for reference:
authorities
0
authority "ROLE_USER" **//says ROLE_USER even when the user belongs to the admin group**
attributes
at_hash "xxxxx"
sub "xxxx"
iss "https://******/oidc/2"
groups
0 "Group A"
1 "Group B"
2 **"DEMO"**
3 **"DEMO Admin"** **//presence in this group should be considered for authorisation**
preferred_username "xxx"
given_name "xxxx"
nonce "xxxxxxx"
sid "xxxxxxx"
aud
0 "xxxxxxx"
updated_at "xxxxxx"
name "xxxxxx"
exp "xxxxxxx"
family_name "xxxxxx"
iat "xxxxxxxx"
email "xxxxxxxx"
idToken {…}
userInfo {…}
1
authority "SCOPE_email"
2
authority "SCOPE_groups"
3
authority "SCOPE_openid"
4
authority "SCOPE_profile"
I want to secure my rest controllers something like this:
@PreAuthorize("Belongs to group admin")
@RequestMapping(value = "/delete", method = RequestMethod.GET)
public string delete() {
System.out.println("delete");
}
This is my application.yaml file
server:
servlet:
context-path: /demo
spring:
security:
oauth2:
client:
registration:
onelogin:
client-id: *****
client-secret: *******
scope: openid,profile,email,groups
provider: onelogin
provider:
onelogin:
issuer-uri: https://******/oidc/2
回答1:
Since your application is also a resource server, you can use a custom JwtAuthenticationConverter to configure how the JWT gets converted to an Authentication object. Specifically for this case, you can configure how the JWT gets converted to the list of GrantedAuthorities.
By default, the resource server populates the GrantedAuthorities based on the "scope" claim.
If the JWT contains a claim with the name "scope" or "scp", then Spring Security will use the value in that claim to construct the authorities by prefixing each value with "SCOPE_". That is why you see the authorities "SCOPE_email", "SCOPE_groups" etc
If you want to populate the GrantedAuthorities based on the "groups" claim instead, you can do so like this:
@Bean
public JwtAuthenticationConverter jwtAuthenticationConverter() {
JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
converter.setJwtGrantedAuthoritiesConverter(new CustomJwtGrantedAuthoritiesConverter());
return converter;
}
public class CustomJwtGrantedAuthoritiesConverter implements Converter<Jwt, Collection<GrantedAuthority>> {
@Override
public Collection<GrantedAuthority> convert(Jwt jwt) {
Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
for (String group : getGroups(jwt)) {
grantedAuthorities.add(new SimpleGrantedAuthority(group));
}
return grantedAuthorities;
}
}
private Collection<String> getGroups(Jwt jwt) {
Object groups = jwt.getClaim("groups");
// Convert groups to Collection of Strings based on your logic
}
Then you can use the expression "hasAuthority('YOUR_CUSTOM_GROUP_NAME')" to restrict access to certain endpoints.
来源:https://stackoverflow.com/questions/64645351/role-based-authorization-oauth-with-onelogin-and-spring-security