Pārlūkot izejas kodu

Completed implementation in ClaimAccessor's

Fixes gh-4449
Joe Grandja 8 gadi atpakaļ
vecāks
revīzija
c204cc2c31

+ 3 - 3
oauth2/jwt-jose/src/main/java/org/springframework/security/jwt/JwtClaimAccessor.java

@@ -19,6 +19,7 @@ import org.springframework.security.oauth2.core.ClaimAccessor;
 
 import java.net.URL;
 import java.time.Instant;
+import java.util.List;
 
 /**
  * A {@link ClaimAccessor} for the "Registered Claim Names"
@@ -41,9 +42,8 @@ public interface JwtClaimAccessor extends ClaimAccessor {
 		return this.getClaimAsString(JwtClaim.SUB);
 	}
 
-	default String[] getAudience() {
-		// TODO Impl JwtClaim.AUD
-		return null;
+	default List<String> getAudience() {
+		return this.getClaimAsStringList(JwtClaim.AUD);
 	}
 
 	default Instant getExpiresAt() {

+ 21 - 0
oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClaimAccessor.java

@@ -20,6 +20,9 @@ import org.springframework.util.Assert;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.time.Instant;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -66,4 +69,22 @@ public interface ClaimAccessor {
 			throw new IllegalArgumentException("Unable to convert claim '" + claim + "' to URL: " + ex.getMessage(), ex);
 		}
 	}
+
+	default Map<String, Object> getClaimAsMap(String claim) {
+		if (!this.containsClaim(claim) || !Map.class.isAssignableFrom(this.getClaims().get(claim).getClass())) {
+			return null;
+		}
+		Map<String, Object> claimFields = new HashMap<>();
+		((Map<?, ?>)this.getClaims().get(claim)).forEach((k, v) -> claimFields.put(k.toString(), v));
+		return claimFields;
+	}
+
+	default List<String> getClaimAsStringList(String claim) {
+		if (!this.containsClaim(claim) || !List.class.isAssignableFrom(this.getClaims().get(claim).getClass())) {
+			return null;
+		}
+		List<String> claimValues = new ArrayList<>();
+		((List<?>)this.getClaims().get(claim)).forEach(e -> claimValues.add(e.toString()));
+		return claimValues;
+	}
 }

+ 92 - 0
oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/Address.java

@@ -15,6 +15,8 @@
  */
 package org.springframework.security.oauth2.oidc.core;
 
+import java.util.Map;
+
 /**
  * The Address Claim represents a physical mailing address defined by the <i>OpenID Connect Core 1.0</i> specification
  * that can be returned either in the <i>UserInfo Response</i> or the <i>ID Token</i>.
@@ -39,4 +41,94 @@ public interface Address {
 
 	String getCountry();
 
+	class Builder implements Address {
+		private static final String FORMATTED_FIELD_NAME = "formatted";
+		private static final String STREET_ADDRESS_FIELD_NAME = "street_address";
+		private static final String LOCALITY_FIELD_NAME = "locality";
+		private static final String REGION_FIELD_NAME = "region";
+		private static final String POSTAL_CODE_FIELD_NAME = "postal_code";
+		private static final String COUNTRY_FIELD_NAME = "country";
+		private String formatted;
+		private String streetAddress;
+		private String locality;
+		private String region;
+		private String postalCode;
+		private String country;
+
+		public Builder() {
+		}
+
+		public Builder(Map<String, Object> addressFields) {
+			this.formatted((String)addressFields.get(FORMATTED_FIELD_NAME));
+			this.streetAddress((String)addressFields.get(STREET_ADDRESS_FIELD_NAME));
+			this.locality((String)addressFields.get(LOCALITY_FIELD_NAME));
+			this.region((String)addressFields.get(REGION_FIELD_NAME));
+			this.postalCode((String)addressFields.get(POSTAL_CODE_FIELD_NAME));
+			this.country((String)addressFields.get(COUNTRY_FIELD_NAME));
+		}
+
+		public Builder formatted(String formatted) {
+			this.formatted = formatted;
+			return this;
+		}
+
+		public Builder streetAddress(String streetAddress) {
+			this.streetAddress = streetAddress;
+			return this;
+		}
+
+		public Builder locality(String locality) {
+			this.locality = locality;
+			return this;
+		}
+
+		public Builder region(String region) {
+			this.region = region;
+			return this;
+		}
+
+		public Builder postalCode(String postalCode) {
+			this.postalCode = postalCode;
+			return this;
+		}
+
+		public Builder country(String country) {
+			this.country = country;
+			return this;
+		}
+
+		public Address build() {
+			return this;
+		}
+
+		@Override
+		public String getFormatted() {
+			return this.formatted;
+		}
+
+		@Override
+		public String getStreetAddress() {
+			return this.streetAddress;
+		}
+
+		@Override
+		public String getLocality() {
+			return this.locality;
+		}
+
+		@Override
+		public String getRegion() {
+			return this.region;
+		}
+
+		@Override
+		public String getPostalCode() {
+			return this.postalCode;
+		}
+
+		@Override
+		public String getCountry() {
+			return this.country;
+		}
+	}
 }

+ 5 - 6
oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/IdTokenClaimAccessor.java

@@ -19,6 +19,7 @@ import org.springframework.security.oauth2.core.ClaimAccessor;
 
 import java.net.URL;
 import java.time.Instant;
+import java.util.List;
 
 /**
  * A {@link ClaimAccessor} for the &quot;Claims&quot; that can be returned in the <i>ID Token</i>
@@ -44,9 +45,8 @@ public interface IdTokenClaimAccessor extends StandardClaimAccessor {
 		return this.getClaimAsString(IdTokenClaim.SUB);
 	}
 
-	default String[] getAudience() {
-		// TODO Impl IdTokenClaim.AUD
-		return null;
+	default List<String> getAudience() {
+		return this.getClaimAsStringList(IdTokenClaim.AUD);
 	}
 
 	default Instant getExpiresAt() {
@@ -69,9 +69,8 @@ public interface IdTokenClaimAccessor extends StandardClaimAccessor {
 		return this.getClaimAsString(IdTokenClaim.ACR);
 	}
 
-	default String[] getAuthenticationMethods() {
-		// TODO Impl IdTokenClaim.AMR
-		return null;
+	default List<String> getAuthenticationMethods() {
+		return this.getClaimAsStringList(IdTokenClaim.AMR);
 	}
 
 	default String getAuthorizedParty() {

+ 5 - 3
oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/StandardClaimAccessor.java

@@ -18,6 +18,7 @@ package org.springframework.security.oauth2.oidc.core;
 import org.springframework.security.oauth2.core.ClaimAccessor;
 
 import java.time.Instant;
+import java.util.Map;
 
 /**
  * A {@link ClaimAccessor} for the &quot;Standard Claims&quot; that can be returned
@@ -107,12 +108,13 @@ public interface StandardClaimAccessor extends ClaimAccessor {
 	}
 
 	default Address getAddress() {
-		// TODO Impl StandardClaim.ADDRESS
-		return null;
+		Map<String, Object> addressFields = this.getClaimAsMap(StandardClaim.ADDRESS);
+		return (addressFields != null ?
+			new Address.Builder(addressFields).build() :
+			new Address.Builder().build());
 	}
 
 	default Instant getUpdatedAt() {
 		return this.getClaimAsInstant(StandardClaim.UPDATED_AT);
 	}
-
 }

+ 2 - 2
samples/boot/oauth2login/src/main/resources/META-INF/oauth2-clients-defaults.yml

@@ -5,7 +5,7 @@ security:
         client-authentication-method: basic
         authorized-grant-type: authorization_code
         redirect-uri: "{scheme}://{serverName}:{serverPort}{baseAuthorizeUri}/{clientAlias}"
-        scopes: openid, email, profile
+        scopes: openid, profile, email, address, phone
         authorization-uri: "https://accounts.google.com/o/oauth2/auth"
         token-uri: "https://accounts.google.com/o/oauth2/token"
         user-info-uri: "https://www.googleapis.com/oauth2/v3/userinfo"
@@ -38,6 +38,6 @@ security:
         client-authentication-method: basic
         authorized-grant-type: authorization_code
         redirect-uri: "{scheme}://{serverName}:{serverPort}{baseAuthorizeUri}/{clientAlias}"
-        scopes: openid, email, profile
+        scopes: openid, profile, email, address, phone
         client-name: Okta
         client-alias: okta