问题
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