diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/NamedAdminAuthoritiesMapper.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/NamedAdminAuthoritiesMapper.java new file mode 100644 index 000000000..27ed7bcec --- /dev/null +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/NamedAdminAuthoritiesMapper.java @@ -0,0 +1,81 @@ +/** + * + */ +package org.mitre.openid.connect.client; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; +import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper; + +/** + * + * Simple mapper that adds ROLE_USER to the authorities map for all queries, + * plus adds ROLE_ADMIN if the subject and issuer pair are found in the + * configurable "admins" set. + * + * @author jricher + * + */ +public class NamedAdminAuthoritiesMapper implements GrantedAuthoritiesMapper { + + private static final SimpleGrantedAuthority ROLE_ADMIN = new SimpleGrantedAuthority("ROLE_ADMIN"); + private static final SimpleGrantedAuthority ROLE_USER = new SimpleGrantedAuthority("ROLE_USER"); + + private Set admins = new HashSet(); + + private GrantedAuthoritiesMapper chain = new NullAuthoritiesMapper(); + + @Override + public Collection mapAuthorities(Collection authorities) { + + Set out = new HashSet(); + out.addAll(authorities); + + for (GrantedAuthority authority : authorities) { + if (admins.contains(authority)) { + out.add(ROLE_ADMIN); + } + } + + // everybody's a user by default + out.add(ROLE_USER); + + return chain.mapAuthorities(out); + } + + /** + * @return the admins + */ + public Set getAdmins() { + return admins; + } + + /** + * @param admins the admins to set + */ + public void setAdmins(Set admins) { + this.admins = admins; + } + + /** + * @return the chain + */ + public GrantedAuthoritiesMapper getChain() { + return chain; + } + + /** + * @param chain the chain to set + */ + public void setChain(GrantedAuthoritiesMapper chain) { + this.chain = chain; + } + +} diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java index 478f3c9de..fdb4c5261 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java @@ -22,12 +22,14 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper; import org.springframework.security.core.userdetails.UsernameNotFoundException; import com.google.common.base.Strings; +import com.google.common.collect.Lists; import com.google.common.collect.Sets; /** @@ -39,7 +41,7 @@ public class OIDCAuthenticationProvider implements private UserInfoFetcher userInfoFetcher = new UserInfoFetcher(); - private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper(); + private GrantedAuthoritiesMapper authoritiesMapper = new NamedAdminAuthoritiesMapper(); /* * (non-Javadoc) @@ -67,12 +69,11 @@ public class OIDCAuthenticationProvider implements if (authentication instanceof OIDCAuthenticationToken) { - // Default authorities set - // TODO: let this be configured - Collection authorities = Sets.newHashSet(new SimpleGrantedAuthority("ROLE_USER")); OIDCAuthenticationToken token = (OIDCAuthenticationToken) authentication; + Collection authorities = Lists.newArrayList(new SubjectIssuerGrantedAuthority(token.getSub(), token.getIssuer())); + UserInfo userInfo = userInfoFetcher.loadUserInfo(token); if (userInfo == null) { diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/SubjectIssuerGrantedAuthority.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/SubjectIssuerGrantedAuthority.java new file mode 100644 index 000000000..b73605ca7 --- /dev/null +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/SubjectIssuerGrantedAuthority.java @@ -0,0 +1,110 @@ +/** + * + */ +package org.mitre.openid.connect.client; + +import org.springframework.security.core.GrantedAuthority; + +import com.google.common.base.Strings; + +/** + * + * Simple authority representing a user at an issuer. + * + * @author jricher + * + */ +public class SubjectIssuerGrantedAuthority implements GrantedAuthority { + + private static final long serialVersionUID = 5584978219226664794L; + + private final String subject; + private final String issuer; + + /** + * @param subject + * @param issuer + */ + public SubjectIssuerGrantedAuthority(String subject, String issuer) { + if (Strings.isNullOrEmpty(subject) || Strings.isNullOrEmpty(issuer)) { + throw new IllegalArgumentException("Neither subject nor issuer may be null or empty"); + } + this.subject = subject; + this.issuer = issuer; + } + + /** + * Returns a string formed by concatenating the subject with the issuer, separated by _ and prepended with OIDC_ + * + * For example, the user "bob" from issuer "http://id.example.com/" would return the authority string of: + * + * OIDC_bob_http://id.example.com/ + */ + @Override + public String getAuthority() { + return "OIDC_" + subject + "_" + issuer; + } + + /** + * @return the subject + */ + public String getSubject() { + return subject; + } + + /** + * @return the issuer + */ + public String getIssuer() { + return issuer; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((issuer == null) ? 0 : issuer.hashCode()); + result = prime * result + ((subject == null) ? 0 : subject.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof SubjectIssuerGrantedAuthority)) { + return false; + } + SubjectIssuerGrantedAuthority other = (SubjectIssuerGrantedAuthority) obj; + if (issuer == null) { + if (other.issuer != null) { + return false; + } + } else if (!issuer.equals(other.issuer)) { + return false; + } + if (subject == null) { + if (other.subject != null) { + return false; + } + } else if (!subject.equals(other.subject)) { + return false; + } + return true; + } + + @Override + public String toString() { + return getAuthority(); + } +}