Skip to content

Commit b99f2ac

Browse files
Merge pull request #80 from authlete/feat/x-fapi-interaction-id
feat: FapiInteractionIdResponseFilter
2 parents 27cea72 + f3c1bcd commit b99f2ac

5 files changed

Lines changed: 183 additions & 1 deletion

File tree

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright (C) 2026 Authlete, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing,
11+
* software distributed under the License is distributed on an
12+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13+
* either express or implied. See the License for the specific
14+
* language governing permissions and limitations under the
15+
* License.
16+
*/
17+
package com.authlete.jaxrs.server.decorator;
18+
19+
20+
/**
21+
* Filter and interceptor priorities that are used as a parameter of
22+
* the {@link jakarta.annotation.Priority Priority} annotation.
23+
*
24+
* @see jakarta.annotation.Priority
25+
* @see jakarta.ws.rs.Priorities
26+
*/
27+
public class DecoratorPriorities
28+
{
29+
/*
30+
* Priorities for ContainerResponseFilter implementations.
31+
*
32+
* <p>
33+
* The smaller the priority, the later the filter is executed.
34+
* </p>
35+
*/
36+
public static final int FAPI_INTERACTION_ID_RESPONSE_FILTER = 40200;
37+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright (C) 2026 Authlete, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing,
11+
* software distributed under the License is distributed on an
12+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13+
* either express or implied. See the License for the specific
14+
* language governing permissions and limitations under the
15+
* License.
16+
*/
17+
package com.authlete.jaxrs.server.decorator;
18+
19+
20+
import java.io.IOException;
21+
import java.util.UUID;
22+
import javax.annotation.Priority;
23+
import javax.ws.rs.container.ContainerRequestContext;
24+
import javax.ws.rs.container.ContainerResponseContext;
25+
import javax.ws.rs.container.ContainerResponseFilter;
26+
import javax.ws.rs.ext.Provider;
27+
import com.authlete.jaxrs.server.http.CustomHttpHeaders;
28+
import com.authlete.jaxrs.server.http.RequestUtility;
29+
30+
31+
/**
32+
* A filter to add the {@code x-fapi-interaction-id} HTTP header to the HTTP
33+
* response.
34+
*
35+
* <p>
36+
* When the HTTP request contains the {@code x-fapi-interaction-id} HTTP header,
37+
* the same value is used. Otherwise, a random UUID is generated and used as the
38+
* value of the {@code x-fapi-interaction-id} HTTP header of the HTTP response.
39+
* </p>
40+
*
41+
* @see <a href="https://bitbucket.org/openid/fapi/src/master/FAPI_2_0_Implementation_Advice.md">
42+
* FAPI 2.0 Implementation Advice</a>
43+
*/
44+
@Provider
45+
@Priority(DecoratorPriorities.FAPI_INTERACTION_ID_RESPONSE_FILTER)
46+
public class FapiInteractionIdResponseFilter implements ContainerResponseFilter
47+
{
48+
@Override
49+
public void filter(
50+
ContainerRequestContext requestContext,
51+
ContainerResponseContext responseContext) throws IOException
52+
{
53+
// The value of the x-fapi-interaction-id HTTP header in the HTTP request.
54+
String interactionId = RequestUtility.extractFapiInteractionId(requestContext);
55+
56+
// If the request does not contain the x-fapi-interaction-id HTTP header.
57+
if (interactionId == null)
58+
{
59+
// Generate a random x-fapi-interaction-id.
60+
interactionId = generateInteractionId();
61+
}
62+
63+
// Add the x-fapi-interaction-id HTTP header to the HTTP response.
64+
//
65+
// Note that even if the value of the x-fapi-interaction-id HTTP header
66+
// in the HTTP request is malformed, the malformed value is used as is.
67+
responseContext.getHeaders().add(
68+
CustomHttpHeaders.X_FAPI_INTERACTION_ID, interactionId);
69+
}
70+
71+
72+
private static final String generateInteractionId()
73+
{
74+
return UUID.randomUUID().toString();
75+
}
76+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright (C) 2026 Authlete, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing,
11+
* software distributed under the License is distributed on an
12+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13+
* either express or implied. See the License for the specific
14+
* language governing permissions and limitations under the
15+
* License.
16+
*/
17+
package com.authlete.jaxrs.server.http;
18+
19+
20+
/**
21+
* Custom HTTP headers.
22+
*/
23+
public class CustomHttpHeaders
24+
{
25+
/**
26+
* The FAPI Interaction ID ({@code x-fapi-interaction-id})
27+
*
28+
* @see <a href="https://openid.net/specs/openid-financial-api-part-1-1_0.html">
29+
* FAPI 1.0 Baseline</a>
30+
*
31+
* @see <a href="https://bitbucket.org/openid/fapi/src/master/FAPI_2_0_Implementation_Advice.md">
32+
* FAPI 2.0 Implementation Advice</a>
33+
*/
34+
public static final String X_FAPI_INTERACTION_ID = "x-fapi-interaction-id";
35+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright (C) 2026 Authlete, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing,
11+
* software distributed under the License is distributed on an
12+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13+
* either express or implied. See the License for the specific
14+
* language governing permissions and limitations under the
15+
* License.
16+
*/
17+
package com.authlete.jaxrs.server.http;
18+
19+
20+
import javax.ws.rs.container.ContainerRequestContext;
21+
22+
23+
public class RequestUtility
24+
{
25+
/**
26+
* Extract the value of the {@code x-fapi-interaction-id} header from the
27+
* given {@link ContainerRequestContext} instance.
28+
*/
29+
public static String extractFapiInteractionId(ContainerRequestContext ctx)
30+
{
31+
return ctx.getHeaderString(CustomHttpHeaders.X_FAPI_INTERACTION_ID);
32+
}
33+
}

src/main/webapp/WEB-INF/web.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@
6969
com.authlete.jaxrs.server.api.obb.ConsentsEndpoint,
7070
com.authlete.jaxrs.server.api.obb.ResourcesEndpoint,
7171
org.glassfish.jersey.moxy.json.MoxyJsonFeature,
72-
org.glassfish.jersey.server.mvc.jsp.JspMvcFeature
72+
org.glassfish.jersey.server.mvc.jsp.JspMvcFeature,
73+
com.authlete.jaxrs.server.decorator.FapiInteractionIdResponseFilter,
7374
</param-value>
7475
</init-param>
7576

0 commit comments

Comments
 (0)