-
Notifications
You must be signed in to change notification settings - Fork 3
feature: m2m-gateway-v3 adding DPoP authentication(PIN-8863) #2891
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
paolomanca-pagopa
merged 79 commits into
develop
from
PIN-8863_WI4_added_Dpop_to_m2mGatewayV3_pt2
Feb 8, 2026
Merged
Changes from all commits
Commits
Show all changes
79 commits
Select commit
Hold shift + click to select a range
9b4b2a5
Feature/Added Api DPoP Token generation (PIN-8909_pt2)
rGregnanin 3676768
Fix/Fix Lint and check (PIN-8909_pt2)
rGregnanin d5af01b
Merge branch 'develop' into PIN-8909_WI3_AuthorizationServer_JWT_M2M_…
rGregnanin a6227f8
WIP WI 3 auth server - refactoring generateInteropApiToken
paolomanca-pagopa c3a0078
WIP WI 3 auth server - refactoring generateInteropApiToken - test
paolomanca-pagopa 9e7acb1
WIP WI 3 auth server - tokenService - remove block DPoP for m2m
paolomanca-pagopa 1b616b5
WIP - m2m-gw-v3 - authorization logic
paolomanca-pagopa a24bff4
Merge branch 'develop' into PIN-8909_WI3_AuthorizationServer_JWT_M2M_…
rGregnanin 12af85c
Merge branch 'PIN-8909_WI3_AuthorizationServer_JWT_M2M_DPOP_pt2' into…
paolomanca-pagopa 9ea131c
WIP - m2m-gw-v3 - authorization logic - 2
paolomanca-pagopa 40cd8d5
Access Token Binding Verification (cnf)
paolomanca-pagopa 932be3a
Added bruno collection (PIN-8909)
rGregnanin 6e8363c
auth with DPOP - WIP
paolomanca-pagopa 3b7da2a
Merge branch 'develop' into PIN-8909_WI3_AuthorizationServer_JWT_M2M_…
paolomanca-pagopa 5671c72
strict check in header Auth and DPoP
paolomanca-pagopa 1ce81aa
refactoring to leave untouched common function
paolomanca-pagopa ebf794f
fix wrong deps in dpop validation
paolomanca-pagopa 52bd204
small comments
paolomanca-pagopa 159f454
fix config export declaration
paolomanca-pagopa b27e5a5
revert fix export config
paolomanca-pagopa 830ca7b
fix config export/import
paolomanca-pagopa 806b48e
fix import config
paolomanca-pagopa 507d02c
reafactor first check on Access Token DPoP
paolomanca-pagopa bcf025e
Feature/Added integration/api test (PIN-8909)
rGregnanin a871afb
Merge branch 'develop' into PIN-8909_WI3_AuthorizationServer_JWT_M2M_…
rGregnanin 2713ba3
refactoring DPoP validation in one file
paolomanca-pagopa 0dab72b
Merge branch 'develop' into PIN-8909_WI3_AuthorizationServer_JWT_M2M_…
rGregnanin 96db613
chore/updated as suggested (PIN-8909)
rGregnanin 1d3008a
chore/Added dpopProofJtiAlreadyUsed test (PIN-8909)
rGregnanin a74979e
Merge branch 'develop' into PIN-8909_WI3_AuthorizationServer_JWT_M2M_…
rGregnanin 063fc34
Fix/fix lint(PIN-8909)
rGregnanin 9124118
Chore/Updated as suggested (PIN-8909)
rGregnanin fdb67f3
Merge branch 'develop' into PIN-8909_WI3_AuthorizationServer_JWT_M2M_…
rGregnanin 93ba4ce
Merge branch 'develop' into PIN-8909_WI3_AuthorizationServer_JWT_M2M_…
paolomanca-pagopa a7d9cda
Merge branch 'PIN-8909_WI3_AuthorizationServer_JWT_M2M_DPOP_pt2' into…
paolomanca-pagopa d6c7933
Merge branch 'develop' into PIN-8909_WI3_AuthorizationServer_JWT_M2M_…
paolomanca-pagopa 81ababa
Merge branch 'PIN-8909_WI3_AuthorizationServer_JWT_M2M_DPOP_pt2' into…
paolomanca-pagopa f7f532b
Merge branch 'develop' into PIN-8909_WI3_AuthorizationServer_JWT_M2M_…
rGregnanin 014746e
Merge branch 'PIN-8909_WI3_AuthorizationServer_JWT_M2M_DPOP_pt2' into…
paolomanca-pagopa d9ae60e
refactor internal command and structure
paolomanca-pagopa 2e0966e
enforce check on DPoP token with 401 err
paolomanca-pagopa 0b390e6
jsdoc fix
paolomanca-pagopa 4c39771
enforce, manage error dpop validation
paolomanca-pagopa d9fd0f3
adding check on MTU
paolomanca-pagopa f90b8d0
comments and setup a mockmiddleware to pass tests as usual behavior
paolomanca-pagopa f2ee49c
add skeleton implementation for authenticationDPoPMiddleware.test
paolomanca-pagopa 66a1f7e
adding parseAuthHeader.test in commons-test
paolomanca-pagopa b847cd2
adding test for calculateThumbprint in commons-test
paolomanca-pagopa f46925a
Chore/updated file .bru
rGregnanin f1edf7c
Merge branch 'develop' into PIN-8909_WI3_AuthorizationServer_JWT_M2M_…
rGregnanin d70cd41
Merge branch 'develop' into PIN-8909_WI3_AuthorizationServer_JWT_M2M_…
rGregnanin 44e61c4
refactoring function in dpop-validation package and m2m-gateway-v3, a…
paolomanca-pagopa 6678a09
removing uthenticationDPoPMiddleware.test
paolomanca-pagopa a7d4316
Merge branch 'develop' into PIN-8909_WI3_AuthorizationServer_JWT_M2M_…
rGregnanin cd7940c
chore/updated file create token .bru (PIN-8909)
rGregnanin 6506a59
Merge branch 'PIN-8909_WI3_AuthorizationServer_JWT_M2M_DPOP_pt2' of h…
rGregnanin 78f3b45
Merge branch 'PIN-8909_WI3_AuthorizationServer_JWT_M2M_DPOP_pt2' into…
paolomanca-pagopa 875b9ae
fix test thumbprint
paolomanca-pagopa d5edde7
chore/ resolved minor comment (PIN-8909)
rGregnanin 977560b
Merge branch 'develop' into PIN-8909_WI3_AuthorizationServer_JWT_M2M_…
rGregnanin 1dd9fc3
fix typo in APIerror
paolomanca-pagopa 97112aa
Merge branch 'PIN-8909_WI3_AuthorizationServer_JWT_M2M_DPOP_pt2' into…
paolomanca-pagopa ff6df45
resolving comments on PR
paolomanca-pagopa cd6850e
remove jkt validation from verifyDPoPThumbprintMatch()
paolomanca-pagopa bf3391f
resolve comments on mandatory htm, adding constant to manage htm from…
paolomanca-pagopa f2c1bce
Merge branch 'develop' into PIN-8909_WI3_AuthorizationServer_JWT_M2M_…
paolomanca-pagopa 1be575f
adding support for EC keyType on calculate thumbprint
paolomanca-pagopa 93e479d
check on http header case insensitive
paolomanca-pagopa b4f6d11
Merge branch 'PIN-8909_WI3_AuthorizationServer_JWT_M2M_DPOP_pt2' into…
paolomanca-pagopa b24c19d
refactor calculateThumbprint with parsing alg with type
paolomanca-pagopa cdc8d21
fix/fixed as suggested (PIN-8909)
rGregnanin 3a81691
Merge branch 'PIN-8909_WI3_AuthorizationServer_JWT_M2M_DPOP_pt2' of h…
rGregnanin 5017b68
refactof extraction of Htu and Htm, add test in dpop-validation to ch…
paolomanca-pagopa 6c4479d
Merge branch 'PIN-8909_WI3_AuthorizationServer_JWT_M2M_DPOP_pt2' into…
paolomanca-pagopa ee7396b
rename config var DPOP_HTU_BASE, strictness to check jwk claim
paolomanca-pagopa 09fe778
Feature/added test (PIN-8909)
rGregnanin 10bf608
Merge branch 'PIN-8909_WI3_AuthorizationServer_JWT_M2M_DPOP_pt2' into…
paolomanca-pagopa f30cfe5
Merge branch 'develop' into PIN-8863_WI4_added_Dpop_to_m2mGatewayV3_pt2
rGregnanin af2e1ef
fix build error, rename calculateJWKThumbprint
paolomanca-pagopa File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| import { describe, it, expect, vi, afterEach } from "vitest"; | ||
| import { missingHeader, badDPoPToken } from "pagopa-interop-models"; | ||
| import { | ||
| genericLogger, | ||
| jwtsFromAuthAndDPoPHeaders, | ||
| } from "pagopa-interop-commons"; | ||
|
|
||
| describe("headers", () => { | ||
| // eslint-disable-next-line @typescript-eslint/explicit-function-return-type | ||
| const mockRequest = (headers: Record<string, string | undefined>) => | ||
| ({ | ||
| headers, | ||
| method: "GET", | ||
| url: "/test/example/endpoint", | ||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
| } as any); | ||
|
|
||
| afterEach(() => { | ||
| vi.restoreAllMocks(); | ||
| }); | ||
|
|
||
| describe("jwtsFromAuthAndDPoPHeaders", () => { | ||
| it("Should correctly extract Access Token and DPoP Proof when headers are valid", () => { | ||
| const req = mockRequest({ | ||
| authorization: "DPoP some-access-token", | ||
| dpop: "some-dpop-proof", | ||
| }); | ||
|
|
||
| const result = jwtsFromAuthAndDPoPHeaders(req, genericLogger); | ||
|
|
||
| expect(result).toEqual({ | ||
| accessToken: "some-access-token", | ||
| dpopProofJWS: "some-dpop-proof", | ||
| }); | ||
| }); | ||
|
|
||
| it("Should throw missingHeader('Authorization') if Authorization header is missing", () => { | ||
| const req = mockRequest({ | ||
| dpop: "some-dpop-proof", | ||
| }); | ||
|
|
||
| expect(() => jwtsFromAuthAndDPoPHeaders(req, genericLogger)).toThrowError( | ||
| missingHeader("Authorization") | ||
| ); | ||
| }); | ||
|
|
||
| it("Should throw badDPoPToken if Authorization token scheme is not 'DPoP'", () => { | ||
| const req = mockRequest({ | ||
| authorization: "Bearer some-token", | ||
| dpop: "some-dpop-proof", | ||
| }); | ||
|
|
||
| expect(() => jwtsFromAuthAndDPoPHeaders(req, genericLogger)).toThrowError( | ||
| badDPoPToken | ||
| ); | ||
| }); | ||
|
|
||
| it("Should throw badDPoPToken if Authorization token value is missing", () => { | ||
| const req = mockRequest({ | ||
| authorization: "DPoP", | ||
| dpop: "some-dpop-proof", | ||
| }); | ||
|
|
||
| expect(() => jwtsFromAuthAndDPoPHeaders(req, genericLogger)).toThrowError( | ||
| badDPoPToken | ||
| ); | ||
| }); | ||
|
|
||
| it("Should throw missingHeader('DPoP') if DPoP header is missing", () => { | ||
| const req = mockRequest({ | ||
| authorization: "DPoP valid-token", | ||
| }); | ||
|
|
||
| expect(() => jwtsFromAuthAndDPoPHeaders(req, genericLogger)).toThrowError( | ||
| missingHeader("DPoP") | ||
| ); | ||
| }); | ||
|
|
||
| it("Should throw missingHeader('DPoP') if DPoP header is empty string", () => { | ||
| const req = mockRequest({ | ||
| authorization: "DPoP valid-token", | ||
| dpop: "", | ||
| }); | ||
|
|
||
| expect(() => jwtsFromAuthAndDPoPHeaders(req, genericLogger)).toThrowError( | ||
| missingHeader("DPoP") | ||
| ); | ||
| }); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,19 @@ | ||
| import crypto, { JsonWebKey, KeyObject } from "crypto"; | ||
| import crypto, { createHash, JsonWebKey, KeyObject } from "crypto"; | ||
| import jwksClient, { JwksClient } from "jwks-rsa"; | ||
| import { | ||
| notAnRSAKey, | ||
| invalidKeyLength, | ||
| invalidPublicKey, | ||
| jwkDecodingError, | ||
| invalidJWKClaim, | ||
| notAllowedCertificateException, | ||
| notAllowedMultipleKeysException, | ||
| notAllowedPrivateKeyException, | ||
| keyTypeNotAllowed, | ||
| JWKKeyRS256, | ||
| JWKKeyES256, | ||
| } from "pagopa-interop-models"; | ||
| import { match } from "ts-pattern"; | ||
| import { JWTConfig } from "../config/index.js"; | ||
|
|
||
| export const decodeBase64ToPem = (base64String: string): string => { | ||
|
|
@@ -35,12 +40,40 @@ export const calculateKid = (jwk: JsonWebKey): string => { | |
| const jwkString = JSON.stringify(sortedJwk); | ||
| return crypto.createHash("sha256").update(jwkString).digest("base64url"); | ||
| }; | ||
|
|
||
| /* This is to avoid repeating the logic of the "calculateKid", | ||
| and to have a more meaningful name | ||
| for the generation of the CNF field inside the DPoP tokens */ | ||
| export const calculateDPoPThumbprint = calculateKid; | ||
|
|
||
| export const calculateJWKThumbprint = (jwk: JsonWebKey): string => { | ||
| const parsedJwk = match(jwk.kty) | ||
| .with("RSA", () => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could just parse these with
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
| const result = JWKKeyRS256.safeParse(jwk); | ||
|
|
||
| if (!result.success) { | ||
| throw invalidJWKClaim(); | ||
| } | ||
| return result.data; | ||
| }) | ||
| .with("EC", () => { | ||
| const result = JWKKeyES256.safeParse(jwk); | ||
|
|
||
| if (!result.success) { | ||
| throw invalidJWKClaim(); | ||
| } | ||
| return result.data; | ||
| }) | ||
| .otherwise(() => { | ||
| throw keyTypeNotAllowed(jwk.kty); | ||
| }); | ||
|
|
||
| const canonicalJwk = sortJWK(parsedJwk); | ||
shuyec marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| return createHash("sha256") | ||
| .update(JSON.stringify(canonicalJwk)) | ||
| .digest("base64url"); | ||
| }; | ||
|
|
||
| function assertNotCertificate(key: string): void { | ||
| try { | ||
| new crypto.X509Certificate(key); | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor. In
commons-testwe have the functiongenerateKeySet. We could use that and compare the result ofcalculateThumbprintwith a crypto hash.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer using this static declaration