feat(oidc): token exchange impersonation (#7516)

* add token exchange feature flag

* allow setting reason and actor to access tokens

* impersonation

* set token types and scopes in response

* upgrade oidc to working draft state

* fix tests

* audience and scope validation

* id toke and jwt as input

* return id tokens

* add grant type  token exchange to app config

* add integration tests

* check and deny actors in api calls

* fix instance setting tests by triggering projection on write and cleanup

* insert sleep statements again

* solve linting issues

* add translations

* pin oidc v3.15.0

* resolve comments, add event translation

* fix refreshtoken test

* use ValidateAuthReqScopes from oidc

* apparently the linter can't make up its mind

* persist actor thru refresh tokens and check in tests

* remove unneeded triggers
This commit is contained in:
Tim Möhlmann
2024-03-20 12:18:46 +02:00
committed by GitHub
parent b338171585
commit 6398349c24
104 changed files with 2149 additions and 248 deletions

View File

@@ -115,6 +115,7 @@ export class AppCreateComponent implements OnInit, OnDestroy {
{ type: OIDCGrantType.OIDC_GRANT_TYPE_IMPLICIT, checked: false, disabled: true },
{ type: OIDCGrantType.OIDC_GRANT_TYPE_REFRESH_TOKEN, checked: false, disabled: true },
{ type: OIDCGrantType.OIDC_GRANT_TYPE_DEVICE_CODE, checked: false, disabled: true },
{ type: OIDCGrantType.OIDC_GRANT_TYPE_TOKEN_EXCHANGE, checked: false, disabled: true },
];
public readonly separatorKeysCodes: number[] = [ENTER, COMMA, SPACE];

View File

@@ -105,6 +105,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
OIDCGrantType.OIDC_GRANT_TYPE_IMPLICIT,
OIDCGrantType.OIDC_GRANT_TYPE_DEVICE_CODE,
OIDCGrantType.OIDC_GRANT_TYPE_REFRESH_TOKEN,
OIDCGrantType.OIDC_GRANT_TYPE_TOKEN_EXCHANGE,
];
public oidcAppTypes: OIDCAppType[] = [
OIDCAppType.OIDC_APP_TYPE_WEB,

View File

@@ -213,6 +213,22 @@ export function getAuthMethodFromPartialConfig(config: {
OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_BASIC,
]);
const codeWithExchange = JSON.stringify([
[OIDCResponseType.OIDC_RESPONSE_TYPE_CODE],
[OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE, OIDCGrantType.OIDC_GRANT_TYPE_TOKEN_EXCHANGE].sort(),
OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_BASIC,
]);
const codeWithRefreshAndExchange = JSON.stringify([
[OIDCResponseType.OIDC_RESPONSE_TYPE_CODE],
[
OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE,
OIDCGrantType.OIDC_GRANT_TYPE_REFRESH_TOKEN,
OIDCGrantType.OIDC_GRANT_TYPE_TOKEN_EXCHANGE,
].sort(),
OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_BASIC,
]);
const pkce = JSON.stringify([
[OIDCResponseType.OIDC_RESPONSE_TYPE_CODE],
[OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE],
@@ -237,6 +253,22 @@ export function getAuthMethodFromPartialConfig(config: {
OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_POST,
]);
const postWithExchange = JSON.stringify([
[OIDCResponseType.OIDC_RESPONSE_TYPE_CODE],
[OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE, OIDCGrantType.OIDC_GRANT_TYPE_TOKEN_EXCHANGE].sort(),
OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_POST,
]);
const postWithRefreshAndExchange = JSON.stringify([
[OIDCResponseType.OIDC_RESPONSE_TYPE_CODE],
[
OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE,
OIDCGrantType.OIDC_GRANT_TYPE_REFRESH_TOKEN,
OIDCGrantType.OIDC_GRANT_TYPE_TOKEN_EXCHANGE,
].sort(),
OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_POST,
]);
const deviceCode = JSON.stringify([
[OIDCResponseType.OIDC_RESPONSE_TYPE_CODE],
[OIDCGrantType.OIDC_GRANT_TYPE_DEVICE_CODE],
@@ -263,6 +295,33 @@ export function getAuthMethodFromPartialConfig(config: {
OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE,
]);
const deviceCodeWithCodeAndExchange = JSON.stringify([
[OIDCResponseType.OIDC_RESPONSE_TYPE_CODE],
[
OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE,
OIDCGrantType.OIDC_GRANT_TYPE_DEVICE_CODE,
OIDCGrantType.OIDC_GRANT_TYPE_TOKEN_EXCHANGE,
],
OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE,
]);
const deviceCodeWithCodeAndRefreshAndExchange = JSON.stringify([
[OIDCResponseType.OIDC_RESPONSE_TYPE_CODE],
[
OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE,
OIDCGrantType.OIDC_GRANT_TYPE_DEVICE_CODE,
OIDCGrantType.OIDC_GRANT_TYPE_REFRESH_TOKEN,
OIDCGrantType.OIDC_GRANT_TYPE_TOKEN_EXCHANGE,
],
OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE,
]);
const deviceCodeWithExchange = JSON.stringify([
[OIDCResponseType.OIDC_RESPONSE_TYPE_CODE],
[OIDCGrantType.OIDC_GRANT_TYPE_DEVICE_CODE, OIDCGrantType.OIDC_GRANT_TYPE_TOKEN_EXCHANGE],
OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE,
]);
const deviceCodeWithRefresh = JSON.stringify([
[OIDCResponseType.OIDC_RESPONSE_TYPE_CODE],
[OIDCGrantType.OIDC_GRANT_TYPE_DEVICE_CODE, OIDCGrantType.OIDC_GRANT_TYPE_REFRESH_TOKEN],
@@ -292,6 +351,10 @@ export function getAuthMethodFromPartialConfig(config: {
return CODE_METHOD.key;
case codeWithRefresh:
return CODE_METHOD.key;
case codeWithExchange:
return CODE_METHOD.key;
case codeWithRefreshAndExchange:
return CODE_METHOD.key;
case pkce:
return PKCE_METHOD.key;
@@ -302,6 +365,10 @@ export function getAuthMethodFromPartialConfig(config: {
return POST_METHOD.key;
case postWithRefresh:
return POST_METHOD.key;
case postWithExchange:
return POST_METHOD.key;
case postWithRefreshAndExchange:
return POST_METHOD.key;
case deviceCode:
return DEVICE_CODE_METHOD.key;
@@ -309,8 +376,14 @@ export function getAuthMethodFromPartialConfig(config: {
return DEVICE_CODE_METHOD.key;
case deviceCodeWithRefresh:
return DEVICE_CODE_METHOD.key;
case deviceCodeWithExchange:
return DEVICE_CODE_METHOD.key;
case deviceCodeWithCodeAndRefresh:
return DEVICE_CODE_METHOD.key;
case deviceCodeWithCodeAndExchange:
return DEVICE_CODE_METHOD.key;
case deviceCodeWithCodeAndRefreshAndExchange:
return DEVICE_CODE_METHOD.key;
case pkjwt:
return PK_JWT_METHOD.key;

View File

@@ -2270,7 +2270,8 @@
"0": "Код за оторизация",
"1": "имплицитно",
"2": "Опресняване на токена",
"3": "Код на устройството"
"3": "Код на устройството",
"4": "Размяна на токени"
},
"AUTHMETHOD": {
"0": "Основен",

View File

@@ -2289,7 +2289,8 @@
"0": "Autorizační kód",
"1": "Implicitní",
"2": "Obnovovací Token",
"3": "Kód zařízení"
"3": "Kód zařízení",
"4": "Výměna tokenů"
},
"AUTHMETHOD": {
"0": "Základní",

View File

@@ -2279,7 +2279,8 @@
"0": "Authorization Code",
"1": "Implicit",
"2": "Refresh Token",
"3": "Device Code"
"3": "Device Code",
"4": "Token Exchange"
},
"AUTHMETHOD": {
"0": "Basic",

View File

@@ -2298,7 +2298,8 @@
"0": "Authorization Code",
"1": "Implicit",
"2": "Refresh Token",
"3": "Device Code"
"3": "Device Code",
"4": "Token Exchange"
},
"AUTHMETHOD": {
"0": "Basic",

View File

@@ -2277,7 +2277,8 @@
"0": "Código de autorización",
"1": "Implícito",
"2": "Token de refresco",
"3": "Device Code"
"3": "Device Code",
"4": "Intercambio de tokens"
},
"AUTHMETHOD": {
"0": "Básico",

View File

@@ -2280,7 +2280,8 @@
"0": "Code d'autorisation",
"1": "Implicite",
"2": "Rafraîchir le jeton",
"3": "Device Code"
"3": "Device Code",
"4": "Échange de jetons"
},
"AUTHMETHOD": {
"0": "Basic",

View File

@@ -2280,7 +2280,8 @@
"0": "Authorization Code",
"1": "Implicit",
"2": "Refresh Token",
"3": "Device Code"
"3": "Device Code",
"4": "Token Exchange"
},
"AUTHMETHOD": {
"0": "Basic",

View File

@@ -2271,7 +2271,8 @@
"0": "Authorization Code",
"1": "Implicit",
"2": "Refresh Token",
"3": "Device Code"
"3": "Device Code",
"4": "Token Exchange"
},
"AUTHMETHOD": {
"0": "Basic",

View File

@@ -2277,7 +2277,8 @@
"0": "Код на Овластување",
"1": "Implicit",
"2": "Токен за Освежување",
"3": "Код од Уред"
"3": "Код од Уред",
"4": "Размена на токени"
},
"AUTHMETHOD": {
"0": "Basic",

View File

@@ -2298,7 +2298,8 @@
"0": "Authorization Code",
"1": "Implicit",
"2": "Refresh Token",
"3": "Device Code"
"3": "Device Code",
"4": "Token Exchange"
},
"AUTHMETHOD": {
"0": "Basic",

View File

@@ -2280,7 +2280,8 @@
"0": "Kod autoryzacyjny",
"1": "Implicite",
"2": "Token odświeżający",
"3": "Device Code"
"3": "Device Code",
"4": "Wymiana tokenów"
},
"AUTHMETHOD": {
"0": "Podstawowy",

View File

@@ -2275,7 +2275,8 @@
"0": "Código de Autorização",
"1": "Implícito",
"2": "Token de Atualização",
"3": "Código do Dispositivo"
"3": "Código do Dispositivo",
"4": "Troca de tokens"
},
"AUTHMETHOD": {
"0": "Básico",

View File

@@ -2393,7 +2393,8 @@
"0": "Код авторизации",
"1": "Скрытый",
"2": "Обновить токен",
"3": "Код устройства"
"3": "Код устройства",
"4": "Обмен токенов"
},
"AUTHMETHOD": {
"0": "Basic",

View File

@@ -2279,7 +2279,8 @@
"0": "Authorization Code",
"1": "Implicit",
"2": "Refresh Token",
"3": "Device Code"
"3": "Device Code",
"4": "Token Exchange"
},
"AUTHMETHOD": {
"0": "Basic",