[java-idp-plugin-vci] 02/02: Review authorization-server flow: OP conventions, RFC 8414 metadata validation
Codeberg
noreply at shibboleth.net
Thu Oct 29 06:49:06 UTC 2026
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch main
in repository java-idp-plugin-vci.
View the commit online:
https://codeberg.org/Shibboleth/java-idp-plugin-vci/commit/a88aab03e5fb3b83dcdbe9ac0949f7d83e2f02af
commit a88aab03e5fb3b83dcdbe9ac0949f7d83e2f02af
Author: Janne Lauros <janne.lauros at csc.fi>
AuthorDate: Thu Oct 29 08:48:53 2026 +0200
Review authorization-server flow: OP conventions, RFC 8414 metadata validation
---
README.md | 19 ++-
...esystemAuthorizationServerMetadataResolver.java | 140 +++++++++++++++++++++
.../impl/DefaultMetadataDocumentConfiguration.java | 6 +
.../META-INF/net.shibboleth.idp/postconfig.xml | 2 +-
.../authorization-server-beans.xml | 15 ++-
.../authorization-server-flow.xml | 6 +-
.../plugin/openidvci/conf/openid-vci.properties | 3 +
...temAuthorizationServerMetadataResolverTest.java | 121 ++++++++++++++++++
.../DefaultMetadataDocumentConfigurationTest.java | 8 ++
9 files changed, 304 insertions(+), 16 deletions(-)
diff --git a/README.md b/README.md
index feb2030..6cdfecc 100644
--- a/README.md
+++ b/README.md
@@ -4440,10 +4440,9 @@ Endpoint `/idp/profile/openid/vci/issuer-metadata`, profile ID `http://geant.org
| `issuerMetadataSignatureSigningConfiguration` | SignatureSigningConfiguration | **openidvci.issuerMetadata.SigningConfiguration** | Signing of the metadata. Published unsigned until **openidvci.issuerMetadata.SigningCredentials** exists. Signed metadata is served for `Accept: application/jwt`. |
| `outboundInterceptorFlows` | List<String> | | Interceptor flows run before the response is sent, also for an error response. |
-**OAuth.JWTVCIssuer** (`/idp/profile/oauth/jwt-vc-issuer`) has two settings,
-`inboundInterceptorFlows`, interceptor flows run before the document is formed, and
-`outboundInterceptorFlows` as above. **OAuth.AuthorizationServer**
-(`/idp/profile/oauth/authorization-server`) has one setting, `outboundInterceptorFlows`.
+**OAuth.JWTVCIssuer** (`/idp/profile/oauth/jwt-vc-issuer`) and **OAuth.AuthorizationServer**
+(`/idp/profile/oauth/authorization-server`) have two settings, `inboundInterceptorFlows`,
+interceptor flows run before the document is formed, and `outboundInterceptorFlows` as above.
#### DID.Document
@@ -4726,6 +4725,7 @@ The file comes with the plugin and is loaded automatically.
| `openidvci.authorizationServer.templated` | Boolean | `true` | Whether the file is Velocity. |
| `openidvci.authorizationServer.resolver` | Bean ID | **openidvci.DefaultAuthorizationServerMetadataResolver** | Resolver of the document. |
| `openidvci.authorizationServer.minRefreshDelay`, `…maxRefreshDelay` | Duration | `PT5M`, `PT4H` | Bounds of re-reading the file. |
+| `openidvci.authorizationServer.cacheControl` | String | `max-age=3600` | Cache-Control of the response. |
#### Signing keys
@@ -4797,13 +4797,20 @@ The templates are Velocity, `$issuer`, `$baseUrl` and `$host` are filled in from
When `idp.oidc.issuer` has a path, the JWT VC issuer metadata is at `/.well-known/jwt-vc-issuer`
followed by that path, `https://issuer.example.org/tenant` has it at
`/.well-known/jwt-vc-issuer/tenant`, and the rewrite pattern is that.
+The authorization server metadata is likewise at `/.well-known/oauth-authorization-server`
+followed by that path, `/.well-known/oauth-authorization-server/tenant`.
The JWT VC issuer metadata names one issuer. A credential with a url other than
`idp.oidc.issuer` as its issuer is verified by `x5c`, or needs the `issuer` of the template
changed to that url.
`credential_configurations_supported` is added from *metadata/verifiable-credentials.json*. The
Credential Issuer metadata endpoint answers `500 server_error` when `credential_endpoint` or
-`credential_configurations_supported` is missing. `batch_credential_issuance.batch_size` is the
-most proofs a credential request may carry, it overrides `batchSize` of the profile.
+`credential_configurations_supported` is missing. The authorization server metadata endpoint
+answers `500 server_error` when `issuer`, `token_endpoint` or `grant_types_supported` is
+missing, when `authorization_code` is listed without `authorization_endpoint`, when
+`response_types_supported` is missing and a grant type other than the pre-authorized code is
+listed, when `implicit` is listed, or when an endpoint is not an https url.
+`batch_credential_issuance.batch_size` is the most proofs a credential request may carry, it
+overrides `batchSize` of the profile.
`token_endpoint` is the token endpoint of this plugin. The OP's
`/.well-known/openid-configuration` has the OP's own token endpoint.
`dpop_signing_alg_values_supported` should be in step with `idp.oauth2.dpop.proofAlgorithms` of
diff --git a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/metadata/impl/FilesystemAuthorizationServerMetadataResolver.java b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/metadata/impl/FilesystemAuthorizationServerMetadataResolver.java
new file mode 100644
index 0000000..bf909e2
--- /dev/null
+++ b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/metadata/impl/FilesystemAuthorizationServerMetadataResolver.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2025, GÉANT
+ *
+ * Licensed 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.geant.shibboleth.plugin.openidvci.metadata.impl;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.geant.shibboleth.plugin.openidvci.metadata.MetadataDocument;
+import org.springframework.core.io.Resource;
+
+import com.nimbusds.oauth2.sdk.GrantType;
+import com.nimbusds.oauth2.sdk.ParseException;
+import com.nimbusds.oauth2.sdk.as.AuthorizationServerMetadata;
+
+import net.minidev.json.JSONObject;
+
+/**
+ * OAuth 2.0 Authorization Server Metadata read from a file, as in
+ * <a href="https://www.rfc-editor.org/rfc/rfc8414#section-2">RFC 8414</a>.
+ */
+public class FilesystemAuthorizationServerMetadataResolver extends FilesystemMetadataDocumentResolver {
+
+ /** Member listing the response types. */
+ @Nonnull
+ public static final String RESPONSE_TYPES_SUPPORTED = "response_types_supported";
+
+ /** Member listing the grant types. */
+ @Nonnull
+ public static final String GRANT_TYPES_SUPPORTED = "grant_types_supported";
+
+ /** Member of the authorization endpoint. */
+ @Nonnull
+ public static final String AUTHORIZATION_ENDPOINT = "authorization_endpoint";
+
+ /** Member of the token endpoint. */
+ @Nonnull
+ public static final String TOKEN_ENDPOINT = "token_endpoint";
+
+ /** Member referencing the JWK Set. */
+ @Nonnull
+ public static final String JWKS_URI = "jwks_uri";
+
+ /** Pre-authorized code grant type of OpenID4VCI. */
+ @Nonnull
+ public static final String PRE_AUTHORIZED_CODE = "urn:ietf:params:oauth:grant-type:pre-authorized_code";
+
+ /** Suffix of the endpoint members. */
+ @Nonnull
+ public static final String ENDPOINT_SUFFIX = "_endpoint";
+
+ /**
+ * Constructor.
+ *
+ * @param metadata the metadata file
+ *
+ * @throws IOException if the metadata cannot be loaded
+ */
+ public FilesystemAuthorizationServerMetadataResolver(@Nonnull final Resource metadata) throws IOException {
+ super(metadata);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull
+ protected MetadataDocument fromMembers(@Nonnull final Map<String, Object> members) throws ParseException {
+
+ final MetadataDocument document = super.fromMembers(members);
+ final Map<String, Object> documentMembers = document.getMembers();
+ AuthorizationServerMetadata.parse(new JSONObject(documentMembers).toJSONString());
+
+ if (!(documentMembers.get(GRANT_TYPES_SUPPORTED) instanceof List<?> grantTypes)) {
+ throw new ParseException("Authorization Server Metadata has no '" + GRANT_TYPES_SUPPORTED + "'");
+ }
+ if (!List.of(PRE_AUTHORIZED_CODE).equals(grantTypes)
+ && !documentMembers.containsKey(RESPONSE_TYPES_SUPPORTED)) {
+ throw new ParseException("Authorization Server Metadata has no '" + RESPONSE_TYPES_SUPPORTED + "'");
+ }
+ if (grantTypes.contains(GrantType.IMPLICIT.getValue())) {
+ throw new ParseException("Authorization Server Metadata lists the unsupported grant type '"
+ + GrantType.IMPLICIT.getValue() + "'");
+ }
+ if (grantTypes.contains(GrantType.AUTHORIZATION_CODE.getValue())
+ && !documentMembers.containsKey(AUTHORIZATION_ENDPOINT)) {
+ throw new ParseException("Authorization Server Metadata has no '" + AUTHORIZATION_ENDPOINT + "'");
+ }
+ if (!documentMembers.containsKey(TOKEN_ENDPOINT)) {
+ throw new ParseException("Authorization Server Metadata has no '" + TOKEN_ENDPOINT + "'");
+ }
+ for (final Map.Entry<String, Object> member : documentMembers.entrySet()) {
+ if (member.getKey().endsWith(ENDPOINT_SUFFIX) || JWKS_URI.equals(member.getKey())) {
+ validateHttpsUrl(member.getKey(), member.getValue());
+ }
+ }
+ return document;
+ }
+
+ /**
+ * Check the value is an https url with a host.
+ *
+ * @param name name of the member
+ * @param value value of the member
+ * @throws ParseException if the value is not such a url
+ */
+ private static void validateHttpsUrl(@Nonnull final String name, @Nullable final Object value)
+ throws ParseException {
+
+ if (!(value instanceof String url)) {
+ throw new ParseException("'" + name + "' is not a string");
+ }
+ try {
+ final URI parsed = new URI(url);
+ if (!"https".equals(parsed.getScheme()) || parsed.getHost() == null) {
+ throw new ParseException("'" + name + "' " + url + " is not an https url with a host");
+ }
+ } catch (final URISyntaxException e) {
+ throw new ParseException("'" + name + "' " + url + " is not a url", e);
+ }
+ }
+
+}
diff --git a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/config/impl/DefaultMetadataDocumentConfiguration.java b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/config/impl/DefaultMetadataDocumentConfiguration.java
index b768fc4..7c52e15 100644
--- a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/config/impl/DefaultMetadataDocumentConfiguration.java
+++ b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/config/impl/DefaultMetadataDocumentConfiguration.java
@@ -42,6 +42,12 @@ public class DefaultMetadataDocumentConfiguration extends AbstractInterceptorAwa
public static final String PROFILE_ID_AUTHORIZATION_SERVER =
"http://geant.org/ns/profiles/oauth/authorization-server";
+ /** Authorization server metadata profile counter name. */
+ @Nonnull
+ @NotEmpty
+ public static final String PROFILE_COUNTER_AUTHORIZATION_SERVER =
+ "net.shibboleth.idp.profiles.oauth.authorization-server";
+
/** ID for the did:web document profile configuration. */
@Nonnull
@NotEmpty
diff --git a/openid-vci-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml b/openid-vci-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
index 62058ba..d6fa8df 100644
--- a/openid-vci-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
+++ b/openid-vci-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
@@ -172,7 +172,7 @@
<!-- Authorization server metadata, published at /.well-known/oauth-authorization-server. -->
<bean id="openidvci.DefaultAuthorizationServerMetadataResolver" lazy-init="true"
- class="org.geant.shibboleth.plugin.openidvci.metadata.impl.FilesystemMetadataDocumentResolver"
+ class="org.geant.shibboleth.plugin.openidvci.metadata.impl.FilesystemAuthorizationServerMetadataResolver"
depends-on="shibboleth.LoggingService"
p:id="openidvci.DefaultAuthorizationServerMetadataResolver"
p:minRefreshDelay="%{openidvci.authorizationServer.minRefreshDelay:PT5M}"
diff --git a/openid-vci-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth/authorization-server/authorization-server-beans.xml b/openid-vci-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth/authorization-server/authorization-server-beans.xml
index 2445724..9462320 100644
--- a/openid-vci-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth/authorization-server/authorization-server-beans.xml
+++ b/openid-vci-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth/authorization-server/authorization-server-beans.xml
@@ -11,10 +11,14 @@
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
default-init-method="initialize" default-destroy-method="destroy">
- <bean id="openidvci.profileId" class="java.lang.String" c:_0="http://geant.org/ns/profiles/oauth/authorization-server"/>
+ <bean id="openidvci.profileId" class="java.lang.String"
+ c:_0="#{T(org.geant.shibboleth.plugin.openidvci.profile.config.impl.DefaultMetadataDocumentConfiguration).PROFILE_ID_AUTHORIZATION_SERVER}"/>
<bean id="openidvci.loggingId" class="java.lang.String"
c:_0="%{openidvci.logging.authorization-server:OAuth.AuthorizationServer}"/>
+ <util:constant id="shibboleth.metrics.ProfileCounter"
+ static-field="org.geant.shibboleth.plugin.openidvci.profile.config.impl.DefaultMetadataDocumentConfiguration.PROFILE_COUNTER_AUTHORIZATION_SERVER"/>
+
<bean id="InitializeUnverifiedRelyingPartyContext"
class="net.shibboleth.idp.plugin.oidc.op.profile.impl.InitializeUnverifiedRelyingPartyContext" scope="prototype" />
@@ -22,7 +26,8 @@
class="org.geant.shibboleth.plugin.openidvci.profile.impl.FormOutboundMetadataDocumentResponseMessage"
scope="prototype"
p:metadataResolver-ref="#{'%{openidvci.authorizationServer.resolver:openidvci.DefaultAuthorizationServerMetadataResolver}'.trim()}"
- p:httpServletResponseSupplier-ref="shibboleth.HttpServletResponseSupplier" />
+ p:httpServletResponseSupplier-ref="shibboleth.HttpServletResponseSupplier"
+ p:cacheControl="%{openidvci.authorizationServer.cacheControl:max-age=3600}" />
<bean id="BuildErrorResponseFromEvent" class="net.shibboleth.oidc.profile.impl.BuildJSONErrorResponseFromEvent"
scope="prototype" p:defaultStatusCode="500" p:defaultCode="server_error"
@@ -30,12 +35,6 @@
<property name="eventContextLookupStrategy">
<bean class="net.shibboleth.idp.profile.context.navigate.WebFlowCurrentEventLookupFunction" />
</property>
- <property name="mappedErrors">
- <map value-type="com.nimbusds.oauth2.sdk.ErrorObject">
- <entry key="#{T(org.opensaml.profile.action.EventIds).IO_ERROR}"
- value="#{T(com.nimbusds.oauth2.sdk.OAuth2Error).SERVER_ERROR}" />
- </map>
- </property>
</bean>
</beans>
diff --git a/openid-vci-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth/authorization-server/authorization-server-flow.xml b/openid-vci-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth/authorization-server/authorization-server-flow.xml
index 984ad55..ba025ac 100644
--- a/openid-vci-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth/authorization-server/authorization-server-flow.xml
+++ b/openid-vci-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth/authorization-server/authorization-server-flow.xml
@@ -5,6 +5,9 @@
parent="openid/vci/abstract-api">
<action-state id="InitializeMandatoryContexts">
+ <on-entry>
+ <set name="flowScope.transitionAfterInboundIntercept" value="'BuildResponseMessage'"/>
+ </on-entry>
<evaluate expression="InitializeProfileRequestContext" />
<evaluate expression="PopulateMetricContext" />
<evaluate expression="FlowStartPopulateAuditContext" />
@@ -12,9 +15,10 @@
<evaluate expression="InitializeUnverifiedRelyingPartyContext" />
<evaluate expression="SelectRelyingPartyConfiguration" />
<evaluate expression="SelectProfileConfiguration" />
+ <evaluate expression="PopulateInboundInterceptContext" />
<evaluate expression="'proceed'" />
- <transition on="proceed" to="BuildResponseMessage" />
+ <transition on="proceed" to="CheckInboundInterceptContext" />
</action-state>
<bean-import resource="classpath:/META-INF/net/shibboleth/idp/flows/oauth/authorization-server/authorization-server-beans.xml" />
diff --git a/openid-vci-impl/src/main/resources/org/geant/shibboleth/plugin/openidvci/conf/openid-vci.properties b/openid-vci-impl/src/main/resources/org/geant/shibboleth/plugin/openidvci/conf/openid-vci.properties
index fa7c9c6..1e3d64f 100644
--- a/openid-vci-impl/src/main/resources/org/geant/shibboleth/plugin/openidvci/conf/openid-vci.properties
+++ b/openid-vci-impl/src/main/resources/org/geant/shibboleth/plugin/openidvci/conf/openid-vci.properties
@@ -104,11 +104,14 @@ openidvci.status-list.index.permutationKey = change_this_to_secret
# /.well-known/oauth-authorization-server. A wallet reads that document to find the endpoints of
# the authorization server this deployment is.
#openidvci.authorizationServer.template = %{idp.home}/static/oauth-authorization-server.json
+# The template is Velocity as above. Set false if the document contains literal '$' or '#'.
#openidvci.authorizationServer.templated = true
#openidvci.authorizationServer.resolver = openidvci.DefaultAuthorizationServerMetadataResolver
# Bounds on the next file refresh of the document
#openidvci.authorizationServer.minRefreshDelay = PT5M
#openidvci.authorizationServer.maxRefreshDelay = PT4H
+# Cache-Control of the response
+#openidvci.authorizationServer.cacheControl = max-age=3600
# Settings for stating this deployment as a Credential Issuer in OpenID Federation. Active
# only when conf/openid-vci-oidfed.xml is imported into conf/global.xml. Set to false to
diff --git a/openid-vci-impl/src/test/java/org/geant/shibboleth/plugin/openidvci/metadata/impl/FilesystemAuthorizationServerMetadataResolverTest.java b/openid-vci-impl/src/test/java/org/geant/shibboleth/plugin/openidvci/metadata/impl/FilesystemAuthorizationServerMetadataResolverTest.java
new file mode 100644
index 0000000..8f8cb51
--- /dev/null
+++ b/openid-vci-impl/src/test/java/org/geant/shibboleth/plugin/openidvci/metadata/impl/FilesystemAuthorizationServerMetadataResolverTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2025, GÉANT
+ *
+ * Licensed 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.geant.shibboleth.plugin.openidvci.metadata.impl;
+
+import java.nio.charset.StandardCharsets;
+
+import org.geant.shibboleth.plugin.openidvci.metadata.MetadataDocument;
+import org.springframework.core.io.ClassPathResource;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import net.shibboleth.shared.component.ComponentInitializationException;
+
+/**
+ * Unit tests for {@link FilesystemAuthorizationServerMetadataResolver}.
+ */
+public class FilesystemAuthorizationServerMetadataResolverTest {
+
+ private static final String TEMPLATE =
+ "org/geant/shibboleth/plugin/openidvci/static/oauth-authorization-server.json";
+
+ private static final String ISSUER = "\"issuer\":\"https://example.org\"";
+
+ private static final String AUTHORIZATION_ENDPOINT =
+ ",\"authorization_endpoint\":\"https://example.org/authorize\"";
+
+ private static final String TOKEN_ENDPOINT = ",\"token_endpoint\":\"https://example.org/token\"";
+
+ private static final String RESPONSE_TYPES = ",\"response_types_supported\":[\"code\"]";
+
+ private static final String GRANT_TYPES = ",\"grant_types_supported\":[\"authorization_code\","
+ + "\"urn:ietf:params:oauth:grant-type:pre-authorized_code\"]";
+
+ private static final String REQUIRED = ISSUER + AUTHORIZATION_ENDPOINT + TOKEN_ENDPOINT + RESPONSE_TYPES
+ + GRANT_TYPES;
+
+ private FilesystemAuthorizationServerMetadataResolver resolverOf(final String content, final boolean templated)
+ throws Exception {
+ final FilesystemAuthorizationServerMetadataResolver resolver =
+ new FilesystemAuthorizationServerMetadataResolver(
+ FilesystemMetadataDocumentResolverTest.fileOf(content));
+ resolver.setId("test");
+ if (templated) {
+ resolver.setVelocityEngine(FilesystemMetadataDocumentResolverTest.velocityEngine());
+ resolver.setIssuer("https://issuer.example.org");
+ }
+ resolver.initialize();
+ return resolver;
+ }
+
+ @Test
+ public void testShippedTemplate() throws Exception {
+ final String template =
+ new String(new ClassPathResource(TEMPLATE).getInputStream().readAllBytes(), StandardCharsets.UTF_8);
+ final MetadataDocument document = resolverOf(template, true).resolveSingle(null);
+
+ Assert.assertNotNull(document);
+ Assert.assertEquals(document.getIssuer().getValue(), "https://issuer.example.org");
+ Assert.assertEquals(document.getMembers().get(FilesystemAuthorizationServerMetadataResolver.TOKEN_ENDPOINT),
+ "https://issuer.example.org/idp/profile/openid/vci/token");
+ }
+
+ @Test
+ public void testExtraMembersKept() throws Exception {
+ final MetadataDocument document = resolverOf("{" + REQUIRED
+ + ",\"client_attestation_pop_signing_alg_values_supported\":[\"ES256\"]"
+ + ",\"authorization_details_types_supported\":[\"openid_credential\"]}", false).resolveSingle(null);
+
+ Assert.assertNotNull(document);
+ Assert.assertTrue(document.getMembers().containsKey("client_attestation_pop_signing_alg_values_supported"));
+ Assert.assertTrue(document.getMembers().containsKey("authorization_details_types_supported"));
+ }
+
+ @Test
+ public void testPreAuthorizedOnlyNeedsNoAuthorizationEndpointNorResponseTypes() throws Exception {
+ final MetadataDocument document = resolverOf("{" + ISSUER + TOKEN_ENDPOINT
+ + ",\"grant_types_supported\":[\"urn:ietf:params:oauth:grant-type:pre-authorized_code\"]}", false)
+ .resolveSingle(null);
+
+ Assert.assertNotNull(document);
+ }
+
+ @DataProvider
+ public Object[][] invalidDocuments() {
+ return new Object[][] {
+ {"{" + ISSUER + TOKEN_ENDPOINT + RESPONSE_TYPES + GRANT_TYPES + "}"},
+ {"{" + ISSUER + AUTHORIZATION_ENDPOINT + RESPONSE_TYPES + GRANT_TYPES + "}"},
+ {"{" + ISSUER + AUTHORIZATION_ENDPOINT + TOKEN_ENDPOINT + GRANT_TYPES + "}"},
+ {"{" + ISSUER + AUTHORIZATION_ENDPOINT + TOKEN_ENDPOINT + RESPONSE_TYPES + "}"},
+ {"{" + ISSUER + AUTHORIZATION_ENDPOINT + TOKEN_ENDPOINT + RESPONSE_TYPES
+ + ",\"grant_types_supported\":[\"authorization_code\",\"implicit\"]}"},
+ {"{" + ISSUER + AUTHORIZATION_ENDPOINT + TOKEN_ENDPOINT + GRANT_TYPES
+ + ",\"response_types_supported\":\"code\"}"},
+ {"{" + REQUIRED + ",\"pushed_authorization_request_endpoint\":\"http://example.org/par\"}"},
+ {"{" + REQUIRED + ",\"pushed_authorization_request_endpoint\":\"/idp/profile/oauth2/par\"}"},
+ {"{" + REQUIRED + ",\"jwks_uri\":\"https://exa mple.org/keyset\"}"},
+ {"{" + REQUIRED + ",\"jwks_uri\":[\"https://example.org/keyset\"]}"},
+ };
+ }
+
+ @Test(dataProvider = "invalidDocuments")
+ public void testInvalid(final String content) {
+ Assert.assertThrows(ComponentInitializationException.class, () -> resolverOf(content, false));
+ }
+
+}
diff --git a/openid-vci-impl/src/test/java/org/geant/shibboleth/plugin/openidvci/profile/config/impl/DefaultMetadataDocumentConfigurationTest.java b/openid-vci-impl/src/test/java/org/geant/shibboleth/plugin/openidvci/profile/config/impl/DefaultMetadataDocumentConfigurationTest.java
index 7fa7185..a911591 100644
--- a/openid-vci-impl/src/test/java/org/geant/shibboleth/plugin/openidvci/profile/config/impl/DefaultMetadataDocumentConfigurationTest.java
+++ b/openid-vci-impl/src/test/java/org/geant/shibboleth/plugin/openidvci/profile/config/impl/DefaultMetadataDocumentConfigurationTest.java
@@ -47,6 +47,14 @@ public class DefaultMetadataDocumentConfigurationTest {
DefaultMetadataDocumentConfiguration.PROFILE_ID_DID_DOCUMENT).size(), 3);
}
+ @Test
+ public void testCountersAreDistinct() {
+ Assert.assertEquals(DefaultMetadataDocumentConfiguration.PROFILE_COUNTER_AUTHORIZATION_SERVER,
+ "net.shibboleth.idp.profiles.oauth.authorization-server");
+ Assert.assertNotEquals(DefaultMetadataDocumentConfiguration.PROFILE_COUNTER_AUTHORIZATION_SERVER,
+ DefaultMetadataDocumentConfiguration.PROFILE_COUNTER_JWT_VC_ISSUER);
+ }
+
@Test
public void testDidDocumentId() {
Assert.assertEquals(new DefaultDidDocumentConfiguration().getId(),
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list