[java-idp-oidc] branch main updated: JOIDC-6 - Release policy for OAuth2 scope values based on IdPAttributes

Henri Mikkonen henri.mikkonen at iki.fi
Tue Jun 21 09:09:39 UTC 2022


This is an automated email from the git hooks/post-receive script.

hjmikkon pushed a commit to branch main
in repository java-idp-oidc.

View the commit online:
http://git.shibboleth.net/view/?p=java-idp-oidc.git;a=commit;h=2e7eb9c58c38a348b08095eeda4327947733b022

The following commit(s) were added to refs/heads/main by this push:
     new 2e7eb9c5 JOIDC-6 - Release policy for OAuth2 scope values based on IdPAttributes
2e7eb9c5 is described below

commit 2e7eb9c58c38a348b08095eeda4327947733b022
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Tue Jun 21 12:08:52 2022 +0300

    JOIDC-6 - Release policy for OAuth2 scope values based on IdPAttributes
    
    https://shibboleth.atlassian.net/browse/JOIDC-6
    
    Included unit tests for ScopeUtil.
---
 .../idp/plugin/oidc/op/profile/ScopeUtilTest.java  | 353 +++++++++++++++++++++
 1 file changed, 353 insertions(+)

diff --git a/idp-oidc-extension-api/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/ScopeUtilTest.java b/idp-oidc-extension-api/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/ScopeUtilTest.java
new file mode 100644
index 00000000..b34914dc
--- /dev/null
+++ b/idp-oidc-extension-api/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/ScopeUtilTest.java
@@ -0,0 +1,353 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.oidc.op.profile;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.nimbusds.oauth2.sdk.Scope;
+
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.resolver.ResolutionException;
+import net.shibboleth.idp.attribute.resolver.scripted.ScriptedIdPAttribute;
+
+/**
+ * Unit tests for {@link ScopeUtil}.
+ */
+public class ScopeUtilTest {
+    
+    final String id = "mockId";
+
+    @Test
+    public void buildAttribute_nullScopeReturnsEmptyValuesList() {
+        final IdPAttribute attribute = ScopeUtil.buildAttribute(id, null);
+        Assert.assertNotNull(attribute);
+        Assert.assertEquals(attribute.getId(), id);
+        assertStringValues(attribute.getValues());
+    }
+
+    @Test
+    public void buildAttribute_emptyScopeReturnsEmptyValuesList() {
+        final IdPAttribute attribute = ScopeUtil.buildAttribute(id, new Scope());
+        Assert.assertNotNull(attribute);
+        Assert.assertEquals(attribute.getId(), id);
+        assertStringValues(attribute.getValues());
+    }
+
+    @Test
+    public void buildAttribute_shouldParseScopeValues() {
+        final IdPAttribute attribute = ScopeUtil.buildAttribute(id, Scope.parse("openid profile email phone"));
+        Assert.assertNotNull(attribute);
+        Assert.assertEquals(attribute.getId(), id);
+        assertStringValues(attribute.getValues(), "openid", "profile", "email", "phone");
+    }
+
+    @Test
+    public void setAttributeValues_nullScopeLeavesInitialValues() {
+        final IdPAttribute attribute = new IdPAttribute(id);
+        attribute.setValues(List.of(new StringAttributeValue("mock1"), new StringAttributeValue("mock2")));
+        ScopeUtil.setAttributeValues(attribute, null);
+        assertStringValues(attribute.getValues(), "mock1", "mock2");
+    }
+
+    @Test
+    public void setAttributeValues_emptyScopeLeavesInitialValues() {
+        final IdPAttribute attribute = new IdPAttribute(id);
+        attribute.setValues(List.of(new StringAttributeValue("mock1"), new StringAttributeValue("mock2")));
+        ScopeUtil.setAttributeValues(attribute, new Scope());
+        assertStringValues(attribute.getValues(), "mock1", "mock2");
+    }
+
+    @Test
+    public void setAttributeValues_scopeValuesSetToAttribute() {
+        final IdPAttribute attribute = new IdPAttribute(id);
+        attribute.setValues(List.of(new StringAttributeValue("mock1"), new StringAttributeValue("mock2")));
+        ScopeUtil.setAttributeValues(attribute, Scope.parse("openid profile email phone"));
+        assertStringValues(attribute.getValues(), "openid", "profile", "email", "phone");
+    }
+
+    @Test
+    public void populateScriptedAttribute_nullScopeLeavesInitialValues() {
+        final ScriptedIdPAttribute attribute = new MockScriptedIdPAttribute(id, "mock1", "mock2");
+        ScopeUtil.populateScriptedAttribute(attribute, (Scope) null);
+        assertStringValues(attribute, "mock1", "mock2");
+    }
+
+    @Test
+    public void populateScriptedAttribute_emptyScopeLeavesInitialValues() {
+        final ScriptedIdPAttribute attribute = new MockScriptedIdPAttribute(id, "mock1", "mock2");
+        ScopeUtil.populateScriptedAttribute(attribute, new Scope());
+        assertStringValues(attribute, "mock1", "mock2");
+    }
+
+    @Test
+    public void populateScriptedAttribute_scopeValuesAddedToAttribute() {
+        final ScriptedIdPAttribute attribute = new MockScriptedIdPAttribute(id, "mock1", "mock2");
+        ScopeUtil.populateScriptedAttribute(attribute, Scope.parse("openid profile email phone"));
+        assertStringValues(attribute, "mock1", "mock2", "openid", "profile", "email", "phone");
+    }
+
+    @Test
+    public void populateScriptedAttribute_nullSourceLeavesInitialValues() throws ResolutionException {
+        final ScriptedIdPAttribute attribute = new MockScriptedIdPAttribute(id, "mock1", "mock2");
+        ScopeUtil.populateScriptedAttribute(attribute, (ScriptedIdPAttribute) null);
+        assertStringValues(attribute, "mock1", "mock2");
+    }
+
+    @Test
+    public void populateScriptedAttribute_emptySourceLeavesInitialValues() throws ResolutionException {
+        final ScriptedIdPAttribute attribute = new MockScriptedIdPAttribute(id, "mock1", "mock2");
+        ScopeUtil.populateScriptedAttribute(attribute, new MockScriptedIdPAttribute("mockId"));
+        assertStringValues(attribute, "mock1", "mock2");
+    }
+
+    @Test
+    public void populateScriptedAttribute_sourceValuesAddedToAttribute() throws ResolutionException {
+        final ScriptedIdPAttribute attribute = new MockScriptedIdPAttribute(id, "mock1", "mock2");
+        ScopeUtil.populateScriptedAttribute(attribute, new MockScriptedIdPAttribute("mockId", "mock3", "mock4"));
+        assertStringValues(attribute, "mock1", "mock2", "mock3", "mock4");
+    }
+
+    @Test
+    public void buildScope_nullAttributeBuildsEmptyScope() {
+        final Scope scope = ScopeUtil.buildScope((IdPAttribute) null);
+        assertScopeValues(scope);
+    }
+
+    @Test
+    public void buildScope_emptyAttributeBuildsEmptyScope() {
+        final Scope scope = ScopeUtil.buildScope(new IdPAttribute(id));
+        assertScopeValues(scope);
+    }
+
+    @Test
+    public void buildScope_attributeValuesAreCopiedToScope() {
+        final IdPAttribute attribute = new IdPAttribute(id);
+        attribute.setValues(List.of(new StringAttributeValue("openid"), new StringAttributeValue("profile")));
+        final Scope scope = ScopeUtil.buildScope(attribute);
+        assertScopeValues(scope, "openid", "profile");
+    }
+
+    @Test
+    public void buildScope_nullScriptedAttributeBuildsEmptyScope() throws ResolutionException {
+        final Scope scope = ScopeUtil.buildScope((ScriptedIdPAttribute) null);
+        assertScopeValues(scope);
+    }
+
+    @Test
+    public void buildScope_emptyScriptedAttributeBuildsEmptyScope() throws ResolutionException {
+        final Scope scope = ScopeUtil.buildScope(new MockScriptedIdPAttribute(id));
+        assertScopeValues(scope);
+    }
+
+    @Test
+    public void buildScope_attributeScriptedValuesAreCopiedToScope() throws ResolutionException {
+        final ScriptedIdPAttribute attribute = new MockScriptedIdPAttribute(id, "openid", "profile");
+        final Scope scope = ScopeUtil.buildScope(attribute);
+        assertScopeValues(scope, "openid", "profile");
+    }
+
+    @Test
+    public void buildIntersectedScope_IdPAttribute_nullAttributeReturnsEmptyScope() {
+        final Scope scope = ScopeUtil.buildIntersectedScope((IdPAttribute) null, Scope.parse("openid profile"));
+        assertScopeValues(scope);
+    }
+
+    @Test
+    public void buildIntersectedScope_IdPAttribute_EmptyAttributeReturnsEmtpyScope() {
+        final Scope scope = ScopeUtil.buildIntersectedScope(new IdPAttribute(id), Scope.parse("openid profile"));
+        assertScopeValues(scope);
+    }
+
+    @Test
+    public void buildIntersectedScope_IdPAttribute_sameAttributeValuesKeepScope() {
+        final IdPAttribute attribute = new IdPAttribute(id);
+        attribute.setValues(List.of(new StringAttributeValue("openid"), new StringAttributeValue("profile")));
+        final Scope scope = ScopeUtil.buildIntersectedScope(attribute, Scope.parse("openid profile"));
+        assertScopeValues(scope, "openid", "profile");
+    }
+
+    @Test
+    public void buildIntersectedScope_IdPAttribute_sameAttributeValuesKeptInScope() {
+        final IdPAttribute attribute = new IdPAttribute(id);
+        attribute.setValues(List.of(new StringAttributeValue("openid")));
+        final Scope scope = ScopeUtil.buildIntersectedScope(attribute, Scope.parse("openid profile"));
+        assertScopeValues(scope, "openid");
+    }
+
+    @Test
+    public void buildIntersectedScope_IdPAttribute_sameScopeValuesKeptInScope() {
+        final IdPAttribute attribute = new IdPAttribute(id);
+        attribute.setValues(List.of(new StringAttributeValue("openid"), new StringAttributeValue("profile")));
+        final Scope scope = ScopeUtil.buildIntersectedScope(attribute, Scope.parse("openid"));
+        assertScopeValues(scope, "openid");
+    }
+
+    @Test
+    public void buildIntersectedScope_IdPAttribute_nullScopeKeepsAttributeValues() {
+        final IdPAttribute attribute = new IdPAttribute(id);
+        attribute.setValues(List.of(new StringAttributeValue("openid"), new StringAttributeValue("profile")));
+        final Scope scope = ScopeUtil.buildIntersectedScope(attribute, null);
+        assertScopeValues(scope, "openid", "profile");
+    }
+
+    @Test
+    public void buildIntersectedScope_IdPAttribute_EmptyScopeReturnsEmtpyScope() {
+        final IdPAttribute attribute = new IdPAttribute(id);
+        attribute.setValues(List.of(new StringAttributeValue("openid"), new StringAttributeValue("profile")));
+        final Scope scope = ScopeUtil.buildIntersectedScope(attribute, new Scope());
+        assertScopeValues(scope);
+    }
+
+    @Test
+    public void buildIntersectedScope_ScriptedIdPAttribute_nullAttributeReturnsEmptyScope()
+            throws ResolutionException {
+        final Scope scope = ScopeUtil.buildIntersectedScope((ScriptedIdPAttribute)null, Scope.parse("openid profile"));
+        assertScopeValues(scope);
+    }
+
+    @Test
+    public void buildIntersectedScope_ScriptedIdPAttribute_EmptyAttributeReturnsEmtpyScope()
+            throws ResolutionException {
+        final Scope scope = ScopeUtil.buildIntersectedScope(new MockScriptedIdPAttribute(id),
+                Scope.parse("openid profile"));
+        assertScopeValues(scope);
+    }
+
+    @Test
+    public void buildIntersectedScope_ScriptedIdPAttribute_sameAttributeValuesKeepScope()
+            throws ResolutionException {
+        final ScriptedIdPAttribute attribute = new MockScriptedIdPAttribute(id, "openid", "profile");
+        final Scope scope = ScopeUtil.buildIntersectedScope(attribute, Scope.parse("openid profile"));
+        assertScopeValues(scope, "openid", "profile");
+    }
+
+    @Test
+    public void buildIntersectedScope_ScriptedIdPAttribute_sameAttributeValuesKeptInScope()
+            throws ResolutionException {
+        final ScriptedIdPAttribute attribute = new MockScriptedIdPAttribute(id, "openid");
+        final Scope scope = ScopeUtil.buildIntersectedScope(attribute, Scope.parse("openid profile"));
+        assertScopeValues(scope, "openid");
+    }
+
+    @Test
+    public void buildIntersectedScope_ScriptedIdPAttribute_sameScopeValuesKeptInScope() throws ResolutionException {
+        final ScriptedIdPAttribute attribute = new MockScriptedIdPAttribute(id, "openid", "profile");
+        final Scope scope = ScopeUtil.buildIntersectedScope(attribute, Scope.parse("openid"));
+        assertScopeValues(scope, "openid");
+    }
+
+    @Test
+    public void buildIntersectedScope_ScriptedIdPAttribute_nullScopeKeepsAttributeValues() throws ResolutionException {
+        final ScriptedIdPAttribute attribute = new MockScriptedIdPAttribute(id, "openid", "profile");
+        final Scope scope = ScopeUtil.buildIntersectedScope(attribute, null);
+        assertScopeValues(scope, "openid", "profile");
+    }
+
+    @Test
+    public void buildIntersectedScope_ScriptedIdPAttribute_EmptyScopeReturnsEmtpyScope() throws ResolutionException {
+        final ScriptedIdPAttribute attribute = new MockScriptedIdPAttribute(id, "openid", "profile");
+        final Scope scope = ScopeUtil.buildIntersectedScope(attribute, new Scope());
+        assertScopeValues(scope);
+    }
+
+    @Test
+    public void removeValue_existingValueRemoved() {
+        final Scope scope = Scope.parse("openid profile");
+        ScopeUtil.removeValue(scope, "profile");
+        assertScopeValues(scope, "openid");
+    }
+
+    @Test
+    public void removeValue_nonExistingValueKeepsOriginal() {
+        final Scope scope = Scope.parse("openid profile");
+        ScopeUtil.removeValue(scope, "email");
+        assertScopeValues(scope, "openid", "profile");
+    }
+
+    protected void assertStringValues(final List<IdPAttributeValue> values, final String... strings) {
+        Assert.assertNotNull(values);
+        Assert.assertEquals(values.size(), strings.length);
+        final List<String> list = List.of(strings);
+        for (final IdPAttributeValue value : values) {
+            Assert.assertTrue(value instanceof StringAttributeValue);
+            Assert.assertTrue(list.contains(((StringAttributeValue) value).getValue()));
+        }
+    }
+
+    protected void assertStringValues(final ScriptedIdPAttribute attribute, final String... strings) {
+        try {
+            final Collection<Object> values = attribute.getValues();
+            Assert.assertEquals(values.size(), strings.length);
+            final List<String> list = List.of(strings);
+            for (final Object value : values) {
+                Assert.assertTrue(value instanceof String);
+                Assert.assertTrue(list.contains((String) value));
+            }
+        } catch (final ResolutionException e) {
+            Assert.fail();
+        }
+    }
+
+    protected void assertScopeValues(final Scope scope, final String... strings) {
+        Assert.assertNotNull(scope);
+        Assert.assertEquals(scope.size(), strings.length);
+        final List<String> list = List.of(strings);
+        for (final String value : scope.toStringList()) {
+            Assert.assertTrue(list.contains(value));
+        }
+    }
+
+    class MockScriptedIdPAttribute implements ScriptedIdPAttribute {
+        
+        private final String id;
+        private final List<Object> values;
+        
+        public MockScriptedIdPAttribute(final String attributeId, final Object... objects) {
+            id = attributeId;
+            values = new ArrayList<>(List.of(objects));
+        }
+
+        @Override
+        public Collection<Object> getValues() throws ResolutionException {
+            return values;
+        }
+
+        @Override
+        public IdPAttribute getNativeAttribute() throws ResolutionException {
+            return null;
+        }
+
+        @Override
+        public String getId() {
+            return id;
+        }
+
+        @Override
+        public void addValue(final Object what) throws ResolutionException {
+            values.add(what);
+        }
+        
+    }
+}

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list