Skip to content

Commit 176dca5

Browse files
committed
APIGW: Enable SAML audience checking
- Audience checking for SAML responses is one way to prevent attackers from reusing e.g. login responses intended for another SP (from a trusted IdP) to log into eVaka - Without audience checking, eVaka would only check that the message came from a trusted IdP and would allow login/logout -> any user that can log in the IdP (AD mainly, in this case) can log into eVaka even if the IdP wouldn't permit it (e.g. missing AD role to access eVaka) - Also sort SAML config attributes alphabetically for consistency
1 parent ae89a6b commit 176dca5

File tree

4 files changed

+29
-21
lines changed

4 files changed

+29
-21
lines changed

apigw/src/shared/auth/ad-saml.ts

+8-9
Original file line numberDiff line numberDiff line change
@@ -101,20 +101,19 @@ export default function createAdStrategy(): SamlStrategy | DevPassportStrategy {
101101
if (!adConfig) throw Error('Missing AD SAML configuration')
102102
return new SamlStrategy(
103103
{
104+
acceptedClockSkewMs: 0,
105+
audience: adConfig.issuer,
104106
callbackUrl: adConfig.callbackUrl,
105-
entryPoint: adConfig.entryPointUrl,
106-
logoutUrl: adConfig.logoutUrl,
107-
issuer: adConfig.issuer,
108107
cert: adConfig.publicCert.map(
109108
(certificateName) => certificates[certificateName]
110109
),
111-
privateCert: readFileSync(adConfig.privateCert, {
112-
encoding: 'utf8'
113-
}),
114-
identifierFormat: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
115110
disableRequestedAuthnContext: true,
116-
signatureAlgorithm: 'sha256',
117-
acceptedClockSkewMs: 0
111+
entryPoint: adConfig.entryPointUrl,
112+
identifierFormat: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
113+
issuer: adConfig.issuer,
114+
logoutUrl: adConfig.logoutUrl,
115+
privateCert: readFileSync(adConfig.privateCert, { encoding: 'utf8' }),
116+
signatureAlgorithm: 'sha256'
118117
},
119118
(profile: Profile, done: VerifiedCallback) => {
120119
// eslint-disable-next-line @typescript-eslint/no-explicit-any

apigw/src/shared/auth/keycloak-saml.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,16 @@ export default function createKeycloakSamlStrategy(): SamlStrategy {
2222
})
2323
return new SamlStrategy(
2424
{
25-
issuer: 'evaka',
26-
callbackUrl: evakaSamlConfig.callbackUrl,
27-
entryPoint: evakaSamlConfig.entryPoint,
28-
logoutUrl: evakaSamlConfig.entryPoint,
2925
acceptedClockSkewMs: 0,
26+
audience: evakaSamlConfig.issuer,
27+
callbackUrl: evakaSamlConfig.callbackUrl,
3028
cert: publicCert,
31-
privateCert: privateCert,
3229
decryptionPvk: privateCert,
30+
entryPoint: evakaSamlConfig.entryPoint,
3331
identifierFormat: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
32+
issuer: 'evaka',
33+
logoutUrl: evakaSamlConfig.entryPoint,
34+
privateCert: privateCert,
3435
signatureAlgorithm: 'sha256'
3536
},
3637
(profile: Profile, done: VerifiedCallback) => {

apigw/src/shared/auth/suomi-fi-saml.ts

+8-7
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,20 @@ export default function createSuomiFiStrategy(): Strategy | DummyStrategy {
6666
})
6767
return new Strategy(
6868
{
69+
acceptedClockSkewMs: 0,
70+
audience: sfiConfig.issuer,
6971
callbackUrl: sfiConfig.callbackUrl,
70-
entryPoint: sfiConfig.entryPoint,
71-
logoutUrl: sfiConfig.logoutUrl,
72-
issuer: sfiConfig.issuer,
7372
cert: sfiConfig.publicCert.map(
7473
(certificateName) => certificates[certificateName]
7574
),
76-
privateCert: privateCert,
7775
decryptionPvk: privateCert,
78-
identifierFormat: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
7976
disableRequestedAuthnContext: true,
80-
signatureAlgorithm: 'sha256',
81-
acceptedClockSkewMs: 0
77+
entryPoint: sfiConfig.entryPoint,
78+
identifierFormat: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
79+
issuer: sfiConfig.issuer,
80+
logoutUrl: sfiConfig.logoutUrl,
81+
privateCert: privateCert,
82+
signatureAlgorithm: 'sha256'
8283
},
8384
(profile: Profile, done: VerifiedCallback) => {
8485
// eslint-disable-next-line @typescript-eslint/no-explicit-any

apigw/src/shared/config.ts

+7
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,13 @@ export const evakaSamlConfig = evakaCallbackUrl
193193
'http://localhost:8080/auth/realms/evaka/protocol/saml'
194194
)
195195
),
196+
issuer: required(
197+
process.env.EVAKA_SAML_ISSUER ??
198+
ifNodeEnv(
199+
['local', 'test'],
200+
'http://localhost:8080/auth/realms/evaka'
201+
)
202+
),
196203
publicCert: required(
197204
process.env.EVAKA_SAML_PUBLIC_CERT ??
198205
ifNodeEnv(['local', 'test'], 'config/test-cert/keycloak-local.pem')

0 commit comments

Comments
 (0)