This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git


The following commit(s) were added to refs/heads/master by this push:
     new 0b5f3cbb oidc-rp: add some tests for the OidcConnectionFinderImpl
0b5f3cbb is described below

commit 0b5f3cbb7a51f728b89731b8669e704b0fbbab83
Author: Robert Munteanu <romb...@apache.org>
AuthorDate: Wed Jul 5 18:23:15 2023 +0300

    oidc-rp: add some tests for the OidcConnectionFinderImpl
---
 org.apache.sling.servlets.oidc-rp/pom.xml          |  31 ++++-
 .../servlets/oidc_rp/impl/OidcCallbackServlet.java |   1 -
 .../oidc_rp/impl/OidcConnectionFinderImpl.java     |   8 +-
 .../oidc_rp/impl/OidcConnectionFinderImplTest.java | 155 +++++++++++++++++++++
 4 files changed, 184 insertions(+), 11 deletions(-)

diff --git a/org.apache.sling.servlets.oidc-rp/pom.xml 
b/org.apache.sling.servlets.oidc-rp/pom.xml
index ea542db1..7a7970d6 100644
--- a/org.apache.sling.servlets.oidc-rp/pom.xml
+++ b/org.apache.sling.servlets.oidc-rp/pom.xml
@@ -256,14 +256,14 @@
         </dependency>
         <dependency>
             <groupId>org.apache.jackrabbit</groupId>
-            <artifactId>jackrabbit-api</artifactId>
-            <version>2.0.0</version>
+            <artifactId>oak-jackrabbit-api</artifactId>
+            <version>1.40.0</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.api</artifactId>
-            <version>2.0.8</version>
+            <version>2.22.0</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
@@ -327,5 +327,30 @@
             <version>3.0.18</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.testing.sling-mock.junit5</artifactId>
+            <version>3.4.2</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.testing.sling-mock-oak</artifactId>
+            <version>3.1.2-1.40.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            
<artifactId>org.apache.sling.jcr.jackrabbit.usermanager</artifactId>
+            <version>2.2.26</version>
+            <scope>test</scope>
+        </dependency>
+        <!-- pin version to override older oak transitively brought in by 
sling-mock -->
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>oak-jcr</artifactId>
+            <version>1.40.0</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
diff --git 
a/org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/servlets/oidc_rp/impl/OidcCallbackServlet.java
 
b/org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/servlets/oidc_rp/impl/OidcCallbackServlet.java
index 769d6414..b6fb06e8 100644
--- 
a/org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/servlets/oidc_rp/impl/OidcCallbackServlet.java
+++ 
b/org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/servlets/oidc_rp/impl/OidcCallbackServlet.java
@@ -125,7 +125,6 @@ public class OidcCallbackServlet extends 
SlingAllMethodsServlet {
             if ( connection.baseUrl() == null )
                 throw new ServletException("Misconfigured baseUrl");
             
-            // TODO - this code should be extracted and reused to refresh the 
access token with a refresh token, if present
             ClientID clientId = new ClientID(connection.clientId());
             Secret clientSecret = new Secret(connection.clientSecret());
             ClientSecretBasic clientCredentials = new 
ClientSecretBasic(clientId, clientSecret);
diff --git 
a/org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/servlets/oidc_rp/impl/OidcConnectionFinderImpl.java
 
b/org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/servlets/oidc_rp/impl/OidcConnectionFinderImpl.java
index 84d273c1..6d56b88a 100644
--- 
a/org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/servlets/oidc_rp/impl/OidcConnectionFinderImpl.java
+++ 
b/org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/servlets/oidc_rp/impl/OidcConnectionFinderImpl.java
@@ -75,13 +75,7 @@ public class OidcConnectionFinderImpl implements 
OidcConnectionFinder, OidcConne
             if ( expiresAt != null  && expiresAt.length == 1 && 
expiresAt[0].getType() == PropertyType.DATE ) {
                 Calendar expiresCal = expiresAt[0].getDate();
                 if ( expiresCal.before(Calendar.getInstance())) {
-                    logger.info("Token for {} expired at {}, not returning", 
connection.name(), expiresCal);
-
-                    Value[] tokenValue = 
user.getProperty(propertyPath(connection, PROPERTY_NAME_REFRESH_TOKEN));
-                    // no refresh token, missing
-                    if ( tokenValue == null ) {
-                        return new OidcToken(OidcTokenState.MISSING, null);
-                    }
+                    logger.info("Token for {} expired at {}, marking as 
expired", connection.name(), expiresCal);
 
                     // refresh token is present, mark as expired
                     return new OidcToken(OidcTokenState.EXPIRED, null);
diff --git 
a/org.apache.sling.servlets.oidc-rp/src/test/java/org/apache/sling/servlets/oidc_rp/impl/OidcConnectionFinderImplTest.java
 
b/org.apache.sling.servlets.oidc-rp/src/test/java/org/apache/sling/servlets/oidc_rp/impl/OidcConnectionFinderImplTest.java
new file mode 100644
index 00000000..5447673e
--- /dev/null
+++ 
b/org.apache.sling.servlets.oidc-rp/src/test/java/org/apache/sling/servlets/oidc_rp/impl/OidcConnectionFinderImplTest.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.sling.servlets.oidc_rp.impl;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.concurrent.TimeUnit;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.jackrabbit.usermanager.impl.AuthorizableAdapterFactory;
+import org.apache.sling.servlets.oidc_rp.OidcConnection;
+import org.apache.sling.servlets.oidc_rp.OidcToken;
+import org.apache.sling.servlets.oidc_rp.OidcTokenState;
+import org.apache.sling.testing.mock.sling.ResourceResolverType;
+import org.apache.sling.testing.mock.sling.junit5.SlingContext;
+import org.apache.sling.testing.mock.sling.junit5.SlingContextExtension;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import com.nimbusds.jwt.JWTClaimsSet;
+import com.nimbusds.jwt.PlainJWT;
+import com.nimbusds.oauth2.sdk.token.BearerAccessToken;
+import com.nimbusds.openid.connect.sdk.token.OIDCTokens;
+
+@ExtendWith(SlingContextExtension.class)
+class OidcConnectionFinderImplTest {
+
+    private final SlingContext context = new 
SlingContext(ResourceResolverType.JCR_OAK);
+    private final MockOidcConnection connection = new MockOidcConnection(new 
String[] {"openid"}, "mock-oidc", "client-id", "client-secret", 
"http://example.com";);
+
+    @BeforeEach
+    public void registerAdapterFactories() {
+        context.registerInjectActivateService(new 
AuthorizableAdapterFactory());
+    }
+
+    @Test
+    void persistTokens_accessTokenOnly() throws LoginException, 
RepositoryException {
+
+        OIDCTokens tokens = new OIDCTokens(new BearerAccessToken(12), null);
+
+        OidcConnectionFinderImpl connectionFinder = new 
OidcConnectionFinderImpl(null);
+        connectionFinder.persistTokens(connection, context.resourceResolver(), 
tokens);
+
+        Resource connectionResource = getConnectionResource(connection);
+
+        ValueMap connectionProps = connectionResource.getValueMap();
+        assertThat(connectionProps)
+            .as("stored tokens for connection")
+            .containsOnlyKeys("jcr:primaryType", "access_token")
+            .containsEntry("access_token", tokens.getAccessToken().getValue());
+    }
+
+    @Test
+    void persistTokens_accessAndIdToken() throws LoginException, 
RepositoryException {
+
+        OIDCTokens tokens = new OIDCTokens(new PlainJWT(new 
JWTClaimsSet.Builder().issuer("example.com").build()), new 
BearerAccessToken(12), null);
+
+        OidcConnectionFinderImpl connectionFinder = new 
OidcConnectionFinderImpl(null);
+        connectionFinder.persistTokens(connection, context.resourceResolver(), 
tokens);
+
+        Resource connectionResource = getConnectionResource(connection);
+
+        ValueMap connectionProps = connectionResource.getValueMap();
+        assertThat(connectionProps)
+            .as("stored tokens for connection")
+            .containsOnlyKeys("jcr:primaryType", "access_token", "id_token")
+            .containsEntry("access_token", tokens.getAccessToken().getValue());
+    }
+
+    
+    @Test
+    void getAccessToken_missing() {
+        
+        OidcConnectionFinderImpl connectionFinder = new 
OidcConnectionFinderImpl(null);
+        
+        OidcToken accessToken = connectionFinder.getAccessToken(connection, 
context.resourceResolver());
+        
+        assertThat(accessToken).as("access token")
+            .isNotNull()
+            .extracting( OidcToken::getState )
+            .isEqualTo( OidcTokenState.MISSING );
+    }
+    
+    @Test
+    void getAccessToken_valid() {
+        
+        OIDCTokens tokens = new OIDCTokens(new BearerAccessToken(12), null);
+
+        OidcConnectionFinderImpl connectionFinder = new 
OidcConnectionFinderImpl(null);
+        connectionFinder.persistTokens(connection, context.resourceResolver(), 
tokens);
+        
+        OidcToken accessToken = connectionFinder.getAccessToken(connection, 
context.resourceResolver());
+        assertThat(accessToken).as("access token")
+            .isNotNull()
+            .extracting( OidcToken::getState , OidcToken::getValue )
+            .containsExactly( OidcTokenState.VALID, 
tokens.getAccessToken().getValue() );
+    }
+
+    @Test
+    void getAccessToken_expired() throws InterruptedException {
+        
+        int lifetimeSeconds = 1;
+        OIDCTokens tokens = new OIDCTokens(new BearerAccessToken(12, 
lifetimeSeconds, null), null);
+        
+        OidcConnectionFinderImpl connectionFinder = new 
OidcConnectionFinderImpl(null);
+        connectionFinder.persistTokens(connection, context.resourceResolver(), 
tokens);
+
+        // wait for the token to expire
+        Thread.sleep( TimeUnit.SECONDS.toMillis( 2 * lifetimeSeconds ) );
+        
+        OidcToken accessToken = connectionFinder.getAccessToken(connection, 
context.resourceResolver());
+        assertThat(accessToken).as("access token")
+            .isNotNull()
+            .extracting( OidcToken::getState )
+            .isEqualTo( OidcTokenState.EXPIRED );
+    }
+
+    private Resource getConnectionResource(OidcConnection connection) throws 
RepositoryException {
+        String userPath = 
context.resourceResolver().adaptTo(User.class).getPath();
+        Resource userHomeResource = 
context.resourceResolver().getResource(userPath);
+        Resource oidcTokensResource = userHomeResource.getChild("oidc-tokens");
+
+        assertThat(oidcTokensResource)
+            .describedAs("oidc-tokens resource")
+            .isNotNull();
+
+        Resource connectionResource = 
oidcTokensResource.getChild(connection.name());
+        assertThat(connectionResource)
+            .as("oidc-tokens/connection resource")
+            .isNotNull();
+        return connectionResource;
+    }
+
+    public record MockOidcConnection(String[] scopes, String name, String 
clientId, String clientSecret, String baseUrl) implements OidcConnection { }
+}

Reply via email to