[java-oidc-common] branch main updated: JCOMOIDC-39 - Add OIDC authentication response message decoders

Phil Smart philip.smart at jisc.ac.uk
Fri Jan 21 14:24:56 UTC 2022


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

philsmart pushed a commit to branch main
in repository java-oidc-common.

View the commit online:
http://git.shibboleth.net/view/?p=java-oidc-common.git;a=commit;h=34030540e7adb07e8dc7558e8f44495506724b7e

The following commit(s) were added to refs/heads/main by this push:
     new 3403054  JCOMOIDC-39 - Add OIDC authentication response message decoders
3403054 is described below

commit 34030540e7adb07e8dc7558e8f44495506724b7e
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Fri Jan 21 14:24:49 2022 +0000

    JCOMOIDC-39 - Add OIDC authentication response message decoders
    
     - Add form_post and query decoders.
     - Uses Nimbus to parse the response into an AuthenticationResponse
    
    https://shibboleth.atlassian.net/browse/JCOMOIDC-39
---
 .../oidc/profile/decoding/OIDCMessageDecoder.java  | 25 ++++++++
 .../impl/HTTPPostAuthnResponseDecoder.java         | 72 +++++++++++++++++++++
 .../impl/HTTPRedirectAuthnResponseDecoder.java     | 72 +++++++++++++++++++++
 .../impl/HTTPPostAuthnResponseDecoderTest.java     | 74 ++++++++++++++++++++++
 .../impl/HTTPRedirectAuthnResponseDecoderTest.java | 74 ++++++++++++++++++++++
 5 files changed, 317 insertions(+)

diff --git a/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/decoding/OIDCMessageDecoder.java b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/decoding/OIDCMessageDecoder.java
new file mode 100644
index 0000000..8ee17b0
--- /dev/null
+++ b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/decoding/OIDCMessageDecoder.java
@@ -0,0 +1,25 @@
+/*
+ * 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.oidc.profile.decoding;
+
+import org.opensaml.messaging.decoder.MessageDecoder;
+
+/** Marker interface for OIDC Message Decoders.*/
+public interface OIDCMessageDecoder extends MessageDecoder {
+
+}
diff --git a/oidc-common-profile-impl/src/main/java/net/shibboleth/oidc/profile/decoding/impl/HTTPPostAuthnResponseDecoder.java b/oidc-common-profile-impl/src/main/java/net/shibboleth/oidc/profile/decoding/impl/HTTPPostAuthnResponseDecoder.java
new file mode 100644
index 0000000..278b49d
--- /dev/null
+++ b/oidc-common-profile-impl/src/main/java/net/shibboleth/oidc/profile/decoding/impl/HTTPPostAuthnResponseDecoder.java
@@ -0,0 +1,72 @@
+/*
+ * 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.oidc.profile.decoding.impl;
+
+import java.io.IOException;
+
+import javax.annotation.Nonnull;
+import javax.servlet.http.HttpServletRequest;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.decoder.MessageDecoder;
+import org.opensaml.messaging.decoder.MessageDecodingException;
+import org.opensaml.messaging.decoder.servlet.AbstractHttpServletRequestMessageDecoder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.nimbusds.oauth2.sdk.ParseException;
+import com.nimbusds.oauth2.sdk.http.ServletUtils;
+import com.nimbusds.openid.connect.sdk.AuthenticationResponse;
+import com.nimbusds.openid.connect.sdk.AuthenticationResponseParser;
+
+import net.shibboleth.oidc.profile.decoding.OIDCMessageDecoder;
+
+/** 
+ * A {@link MessageDecoder message decoder} that decodes an incoming {@link AuthenticationResponse}
+ * when using a form_post response_type.
+ */
+//TODO this is identical to the HTTPRedirectAuthnDecoder because it uses the Nimbus parser.
+// do we leave as a placeholder for when we create our own decoders?
+public class HTTPPostAuthnResponseDecoder extends AbstractHttpServletRequestMessageDecoder implements OIDCMessageDecoder {
+    
+    /** Class logger. */
+    @Nonnull
+    private final Logger log = LoggerFactory.getLogger(HTTPPostAuthnResponseDecoder.class);
+
+    @Override
+    protected void doDecode() throws MessageDecodingException {
+        
+        log.trace("Decoding incomming 'form_post' authentication response");
+        
+        final MessageContext messageContext = new MessageContext();
+        final HttpServletRequest request = getHttpServletRequest();
+        
+        if (!"POST".equalsIgnoreCase(request.getMethod())) {
+            throw new MessageDecodingException("This message decoder only supports the HTTP POST method");
+        }
+        
+        try {
+            final AuthenticationResponse inboundMessage = 
+                    AuthenticationResponseParser.parse(ServletUtils.createHTTPRequest(request));
+            messageContext.setMessage(inboundMessage);
+        } catch (ParseException | IOException e) {
+            log.error("Unable to parse incomming authentication response",e);
+        }
+        setMessageContext(messageContext);        
+    }
+}
diff --git a/oidc-common-profile-impl/src/main/java/net/shibboleth/oidc/profile/decoding/impl/HTTPRedirectAuthnResponseDecoder.java b/oidc-common-profile-impl/src/main/java/net/shibboleth/oidc/profile/decoding/impl/HTTPRedirectAuthnResponseDecoder.java
new file mode 100644
index 0000000..faa2a8c
--- /dev/null
+++ b/oidc-common-profile-impl/src/main/java/net/shibboleth/oidc/profile/decoding/impl/HTTPRedirectAuthnResponseDecoder.java
@@ -0,0 +1,72 @@
+/*
+ * 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.oidc.profile.decoding.impl;
+
+import java.io.IOException;
+
+import javax.annotation.Nonnull;
+import javax.servlet.http.HttpServletRequest;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.decoder.MessageDecoder;
+import org.opensaml.messaging.decoder.MessageDecodingException;
+import org.opensaml.messaging.decoder.servlet.AbstractHttpServletRequestMessageDecoder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.nimbusds.oauth2.sdk.ParseException;
+import com.nimbusds.oauth2.sdk.http.ServletUtils;
+import com.nimbusds.openid.connect.sdk.AuthenticationResponse;
+import com.nimbusds.openid.connect.sdk.AuthenticationResponseParser;
+
+import net.shibboleth.oidc.profile.decoding.OIDCMessageDecoder;
+
+
+/** 
+ * A {@link MessageDecoder message decoder} that decodes an incoming {@link AuthenticationResponse}
+ * when using a query response_mode.
+ */
+//TODO this is identical to the HTTPPostAuthnDecoder because it uses the Nimbus parser.
+public class HTTPRedirectAuthnResponseDecoder extends AbstractHttpServletRequestMessageDecoder implements OIDCMessageDecoder {
+    
+    /** Class logger. */
+    @Nonnull
+    private final Logger log = LoggerFactory.getLogger(HTTPRedirectAuthnResponseDecoder.class);
+
+    @Override
+    protected void doDecode() throws MessageDecodingException {
+        
+        log.trace("Decoding incomming 'query' authentication response");
+        
+        final MessageContext messageContext = new MessageContext();
+        final HttpServletRequest request = getHttpServletRequest();
+        
+        if (!"GET".equalsIgnoreCase(request.getMethod())) {
+            throw new MessageDecodingException("This message decoder only supports the HTTP GET method");
+        }
+        
+        try {
+            final AuthenticationResponse inboundMessage = 
+                    AuthenticationResponseParser.parse(ServletUtils.createHTTPRequest(request));
+            messageContext.setMessage(inboundMessage);
+        } catch (ParseException | IOException e) {
+            log.error("Unable to parse incomming authentication response",e);
+        }
+        setMessageContext(messageContext);        
+    }
+}
diff --git a/oidc-common-profile-impl/src/test/java/net/shibboleth/oidc/profile/decoding/impl/HTTPPostAuthnResponseDecoderTest.java b/oidc-common-profile-impl/src/test/java/net/shibboleth/oidc/profile/decoding/impl/HTTPPostAuthnResponseDecoderTest.java
new file mode 100644
index 0000000..50b3431
--- /dev/null
+++ b/oidc-common-profile-impl/src/test/java/net/shibboleth/oidc/profile/decoding/impl/HTTPPostAuthnResponseDecoderTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.oidc.profile.decoding.impl;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import org.opensaml.messaging.decoder.MessageDecodingException;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.nimbusds.openid.connect.sdk.AuthenticationResponse;
+import com.nimbusds.openid.connect.sdk.AuthenticationSuccessResponse;
+
+public class HTTPPostAuthnResponseDecoderTest {
+    
+    /** Mock servlet response.*/
+    private MockHttpServletRequest mockRequest;
+    
+    /** The encoder to test.*/
+    private HTTPPostAuthnResponseDecoder decoder;
+    
+    @BeforeMethod public void setUp() throws Exception {    
+        decoder = new HTTPPostAuthnResponseDecoder();      
+        mockRequest = new MockHttpServletRequest();        
+    }
+
+    @Test
+    public void testSuccessfulDecoding_Query_AuthCode() throws Exception {
+        mockRequest.setMethod("POST");
+        mockRequest.setRequestURI("/idp/profile/Authn/OIDC/RP/callback");
+        mockRequest.addParameter("state", "91c28622815dd9a92ef7c984c74c9e39.65317332");
+        mockRequest.addParameter("code", "XSpej7DkB2WYcF1Gzth5CCHw6Oxf3gxR");
+        mockRequest.setContentType("application/x-www-form-urlencoded");
+        decoder.setHttpServletRequest(mockRequest);
+        decoder.initialize();
+        decoder.decode();
+        assertNotNull(decoder.getMessageContext());
+        assertNotNull(decoder.getMessageContext().getMessage());
+        assertTrue(decoder.getMessageContext().getMessage() instanceof AuthenticationSuccessResponse);
+        assertTrue(((AuthenticationResponse)
+                decoder.getMessageContext().getMessage()).getState()
+                .getValue().equals("91c28622815dd9a92ef7c984c74c9e39.65317332"));
+        assertTrue(((AuthenticationSuccessResponse)
+                decoder.getMessageContext().getMessage()).getAuthorizationCode()
+                .getValue().equals("XSpej7DkB2WYcF1Gzth5CCHw6Oxf3gxR"));
+    }
+    
+    @Test(expectedExceptions = MessageDecodingException.class)
+    public void testWrongMethod() throws Exception {
+        mockRequest.setMethod("GET");     
+        decoder.setHttpServletRequest(mockRequest);
+        decoder.initialize();
+        decoder.decode();
+    }
+
+
+}
diff --git a/oidc-common-profile-impl/src/test/java/net/shibboleth/oidc/profile/decoding/impl/HTTPRedirectAuthnResponseDecoderTest.java b/oidc-common-profile-impl/src/test/java/net/shibboleth/oidc/profile/decoding/impl/HTTPRedirectAuthnResponseDecoderTest.java
new file mode 100644
index 0000000..49bff29
--- /dev/null
+++ b/oidc-common-profile-impl/src/test/java/net/shibboleth/oidc/profile/decoding/impl/HTTPRedirectAuthnResponseDecoderTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.oidc.profile.decoding.impl;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import org.opensaml.messaging.decoder.MessageDecodingException;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.nimbusds.openid.connect.sdk.AuthenticationResponse;
+import com.nimbusds.openid.connect.sdk.AuthenticationSuccessResponse;
+
+public class HTTPRedirectAuthnResponseDecoderTest {
+    
+    /** Mock servlet response.*/
+    private MockHttpServletRequest mockRequest;
+    
+    /** The encoder to test.*/
+    private HTTPRedirectAuthnResponseDecoder decoder;
+    
+    @BeforeMethod public void setUp() throws Exception {    
+        decoder = new HTTPRedirectAuthnResponseDecoder();      
+        mockRequest = new MockHttpServletRequest();        
+    }
+
+    @Test
+    public void testSuccessfulDecoding_Query_AuthCode() throws Exception {
+        mockRequest.setMethod("GET");
+        mockRequest.setRequestURI("https://localhost/idp/profile/Authn/OIDC/RP/"
+                + "callback?code=XSpej7DkB2WYcF1Gzth5CCHw6Oxf3gxR&state=91c28622815dd9a92ef7c984c74c9e39.65317332");
+        mockRequest.setQueryString("code=XSpej7DkB2WYcF1Gzth5CCHw6Oxf3gxR&state=91c28622815dd9a92ef7c984c74c9e39.65317332");
+        mockRequest.setContentType("application/x-www-form-urlencoded");
+        decoder.setHttpServletRequest(mockRequest);
+        decoder.initialize();
+        decoder.decode();
+        assertNotNull(decoder.getMessageContext());
+        assertNotNull(decoder.getMessageContext().getMessage());
+        assertTrue(decoder.getMessageContext().getMessage() instanceof AuthenticationSuccessResponse);
+        assertTrue(((AuthenticationResponse)
+                decoder.getMessageContext().getMessage()).getState()
+                .getValue().equals("91c28622815dd9a92ef7c984c74c9e39.65317332"));
+        assertTrue(((AuthenticationSuccessResponse)
+                decoder.getMessageContext().getMessage()).getAuthorizationCode()
+                .getValue().equals("XSpej7DkB2WYcF1Gzth5CCHw6Oxf3gxR"));
+    }
+    
+    @Test(expectedExceptions = MessageDecodingException.class)
+    public void testWrongMethod() throws Exception {
+        mockRequest.setMethod("POST");     
+        decoder.setHttpServletRequest(mockRequest);
+        decoder.initialize();
+        decoder.decode();
+    }
+
+
+}

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


More information about the commits mailing list