mirror of
https://github.com/zitadel/zitadel.git
synced 2025-01-07 22:27:40 +00:00
feat(console): device code (#5771)
* feat: device code * device code, create stepper * rm logs * app setup with device code * remove redirects if grant type is device code only * add device code app e2e --------- Co-authored-by: Fabi <fabienne.gerschwiler@gmail.com> Co-authored-by: Elio Bischof <elio@zitadel.com>
This commit is contained in:
parent
35a0977663
commit
2dc016ea3b
@ -30,19 +30,23 @@
|
|||||||
<span class="fill-space"></span>
|
<span class="fill-space"></span>
|
||||||
<div class="app-specs cnsl-secondary-text">
|
<div class="app-specs cnsl-secondary-text">
|
||||||
<div class="row" *ngIf="isOIDC && method && method.responseType !== undefined">
|
<div class="row" *ngIf="isOIDC && method && method.responseType !== undefined">
|
||||||
<span>{{ 'APP.OIDC.RESPONSETYPE' | translate }}</span>
|
<span class="row-entry">{{ 'APP.OIDC.RESPONSETYPE' | translate }}</span>
|
||||||
<span>{{ 'APP.OIDC.RESPONSE.' + method.responseType.toString() | translate }}</span>
|
<span>{{ 'APP.OIDC.RESPONSE.' + method.responseType.toString() | translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="row" *ngIf="isOIDC && method.grantType !== undefined">
|
<div class="row" *ngIf="isOIDC && method.grantType !== undefined">
|
||||||
<span>{{ 'APP.GRANT' | translate }}</span>
|
<span class="row-entry">{{ 'APP.GRANT' | translate }}</span>
|
||||||
<span>{{ 'APP.OIDC.GRANT.' + method.grantType.toString() | translate }}</span>
|
<span
|
||||||
|
><span class="space" *ngFor="let grant of method.grantType">{{
|
||||||
|
'APP.OIDC.GRANT.' + grant.toString() | translate
|
||||||
|
}}</span></span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="row" *ngIf="isOIDC && method.authMethod !== undefined">
|
<div class="row" *ngIf="isOIDC && method.authMethod !== undefined">
|
||||||
<span>{{ 'APP.AUTHMETHOD' | translate }}</span>
|
<span class="row-entry">{{ 'APP.AUTHMETHOD' | translate }}</span>
|
||||||
<span>{{ 'APP.OIDC.AUTHMETHOD.' + method.authMethod.toString() | translate }}</span>
|
<span>{{ 'APP.OIDC.AUTHMETHOD.' + method.authMethod.toString() | translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="row" *ngIf="!isOIDC && method.apiAuthMethod !== undefined">
|
<div class="row" *ngIf="!isOIDC && method.apiAuthMethod !== undefined">
|
||||||
<span>{{ 'APP.AUTHMETHOD' | translate }}</span>
|
<span class="row-entry">{{ 'APP.AUTHMETHOD' | translate }}</span>
|
||||||
<span>{{ 'APP.API.AUTHMETHOD.' + method.apiAuthMethod.toString() | translate }}</span>
|
<span>{{ 'APP.API.AUTHMETHOD.' + method.apiAuthMethod.toString() | translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -155,7 +155,11 @@
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
:first-child {
|
.space {
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row-entry {
|
||||||
margin-right: 1rem;
|
margin-right: 1rem;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
@ -14,7 +14,7 @@ export interface RadioItemAuthType {
|
|||||||
prefix: string;
|
prefix: string;
|
||||||
background: string;
|
background: string;
|
||||||
responseType?: OIDCResponseType;
|
responseType?: OIDCResponseType;
|
||||||
grantType?: OIDCGrantType;
|
grantType?: OIDCGrantType[];
|
||||||
authMethod?: OIDCAuthMethodType;
|
authMethod?: OIDCAuthMethodType;
|
||||||
apiAuthMethod?: APIAuthMethodType;
|
apiAuthMethod?: APIAuthMethodType;
|
||||||
recommended?: boolean;
|
recommended?: boolean;
|
||||||
|
@ -58,13 +58,9 @@
|
|||||||
</form>
|
</form>
|
||||||
</mat-step>
|
</mat-step>
|
||||||
|
|
||||||
<!-- skip for native OIDC and SAML applications -->
|
<!-- skip for SAML applications -->
|
||||||
<mat-step
|
<mat-step
|
||||||
*ngIf="
|
*ngIf="appType?.value?.createType === AppCreateType.OIDC || appType?.value?.createType === AppCreateType.API"
|
||||||
(appType?.value?.createType === AppCreateType.OIDC &&
|
|
||||||
appType?.value.oidcAppType !== OIDCAppType.OIDC_APP_TYPE_NATIVE) ||
|
|
||||||
appType?.value?.createType === AppCreateType.API
|
|
||||||
"
|
|
||||||
[stepControl]="secondFormGroup"
|
[stepControl]="secondFormGroup"
|
||||||
[editable]="true"
|
[editable]="true"
|
||||||
>
|
>
|
||||||
@ -93,9 +89,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</mat-step>
|
</mat-step>
|
||||||
|
|
||||||
<!-- show redirect step only for OIDC apps -->
|
<!-- show redirect step only for OIDC apps -->
|
||||||
<mat-step *ngIf="appType?.value?.createType === AppCreateType.OIDC" [editable]="true">
|
<mat-step
|
||||||
|
*ngIf="appType?.value?.createType === AppCreateType.OIDC && authMethod?.value !== 'DEVICECODE'"
|
||||||
|
[editable]="true"
|
||||||
|
>
|
||||||
<ng-template matStepLabel>{{ 'APP.OIDC.REDIRECTSECTION' | translate }}</ng-template>
|
<ng-template matStepLabel>{{ 'APP.OIDC.REDIRECTSECTION' | translate }}</ng-template>
|
||||||
|
|
||||||
<p class="step-title">{{ 'APP.OIDC.REDIRECTTITLE' | translate }}</p>
|
<p class="step-title">{{ 'APP.OIDC.REDIRECTTITLE' | translate }}</p>
|
||||||
@ -431,7 +429,13 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content" *ngIf="formappType?.value?.createType === AppCreateType.OIDC">
|
<div
|
||||||
|
class="content"
|
||||||
|
*ngIf="
|
||||||
|
formappType?.value?.createType === AppCreateType.OIDC &&
|
||||||
|
!(oidcAppRequest.toObject().appType === OIDCAppType.OIDC_APP_TYPE_NATIVE && grantTypesListContainsOnlyDeviceCode)
|
||||||
|
"
|
||||||
|
>
|
||||||
<div class="formfield full-width">
|
<div class="formfield full-width">
|
||||||
<cnsl-redirect-uris
|
<cnsl-redirect-uris
|
||||||
class="redirect-section"
|
class="redirect-section"
|
||||||
|
@ -32,6 +32,7 @@ import { AppSecretDialogComponent } from '../app-secret-dialog/app-secret-dialog
|
|||||||
import {
|
import {
|
||||||
BASIC_AUTH_METHOD,
|
BASIC_AUTH_METHOD,
|
||||||
CODE_METHOD,
|
CODE_METHOD,
|
||||||
|
DEVICE_CODE_METHOD,
|
||||||
getPartialConfigFromAuthMethod,
|
getPartialConfigFromAuthMethod,
|
||||||
IMPLICIT_METHOD,
|
IMPLICIT_METHOD,
|
||||||
PKCE_METHOD,
|
PKCE_METHOD,
|
||||||
@ -112,6 +113,7 @@ export class AppCreateComponent implements OnInit, OnDestroy {
|
|||||||
{ type: OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE, checked: true, disabled: false },
|
{ type: OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE, checked: true, disabled: false },
|
||||||
{ type: OIDCGrantType.OIDC_GRANT_TYPE_IMPLICIT, checked: false, disabled: true },
|
{ 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_REFRESH_TOKEN, checked: false, disabled: true },
|
||||||
|
{ type: OIDCGrantType.OIDC_GRANT_TYPE_DEVICE_CODE, checked: false, disabled: true },
|
||||||
];
|
];
|
||||||
|
|
||||||
public readonly separatorKeysCodes: number[] = [ENTER, COMMA, SPACE];
|
public readonly separatorKeysCodes: number[] = [ENTER, COMMA, SPACE];
|
||||||
@ -163,7 +165,7 @@ export class AppCreateComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
switch (this.appType?.value.oidcAppType) {
|
switch (this.appType?.value.oidcAppType) {
|
||||||
case OIDCAppType.OIDC_APP_TYPE_NATIVE:
|
case OIDCAppType.OIDC_APP_TYPE_NATIVE:
|
||||||
this.authMethods = [PKCE_METHOD];
|
this.authMethods = [PKCE_METHOD, DEVICE_CODE_METHOD];
|
||||||
|
|
||||||
// automatically set to PKCE and skip step
|
// automatically set to PKCE and skip step
|
||||||
this.oidcAppRequest.setResponseTypesList([OIDCResponseType.OIDC_RESPONSE_TYPE_CODE]);
|
this.oidcAppRequest.setResponseTypesList([OIDCResponseType.OIDC_RESPONSE_TYPE_CODE]);
|
||||||
@ -473,6 +475,13 @@ export class AppCreateComponent implements OnInit, OnDestroy {
|
|||||||
return this.form.get('grantTypesList');
|
return this.form.get('grantTypesList');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get grantTypesListContainsOnlyDeviceCode(): boolean {
|
||||||
|
return (
|
||||||
|
this.oidcAppRequest.toObject().grantTypesList.length === 1 &&
|
||||||
|
this.oidcAppRequest.toObject().grantTypesList[0] === OIDCGrantType.OIDC_GRANT_TYPE_DEVICE_CODE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
get formappType(): AbstractControl | null {
|
get formappType(): AbstractControl | null {
|
||||||
return this.form.get('appType');
|
return this.form.get('appType');
|
||||||
}
|
}
|
||||||
@ -480,9 +489,6 @@ export class AppCreateComponent implements OnInit, OnDestroy {
|
|||||||
get formMetadataUrl(): AbstractControl | null {
|
get formMetadataUrl(): AbstractControl | null {
|
||||||
return this.form.get('metadataUrl');
|
return this.form.get('metadataUrl');
|
||||||
}
|
}
|
||||||
// get formapplicationType(): AbstractControl | null {
|
|
||||||
// return this.form.get('applicationType');
|
|
||||||
// }
|
|
||||||
|
|
||||||
get authMethodType(): AbstractControl | null {
|
get authMethodType(): AbstractControl | null {
|
||||||
return this.form.get('authMethodType');
|
return this.form.get('authMethodType');
|
||||||
|
@ -46,6 +46,7 @@ import {
|
|||||||
BASIC_AUTH_METHOD,
|
BASIC_AUTH_METHOD,
|
||||||
CODE_METHOD,
|
CODE_METHOD,
|
||||||
CUSTOM_METHOD,
|
CUSTOM_METHOD,
|
||||||
|
DEVICE_CODE_METHOD,
|
||||||
getAuthMethodFromPartialConfig,
|
getAuthMethodFromPartialConfig,
|
||||||
getPartialConfigFromAuthMethod,
|
getPartialConfigFromAuthMethod,
|
||||||
IMPLICIT_METHOD,
|
IMPLICIT_METHOD,
|
||||||
@ -89,6 +90,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
|||||||
public oidcGrantTypes: OIDCGrantType[] = [
|
public oidcGrantTypes: OIDCGrantType[] = [
|
||||||
OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE,
|
OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE,
|
||||||
OIDCGrantType.OIDC_GRANT_TYPE_IMPLICIT,
|
OIDCGrantType.OIDC_GRANT_TYPE_IMPLICIT,
|
||||||
|
OIDCGrantType.OIDC_GRANT_TYPE_DEVICE_CODE,
|
||||||
OIDCGrantType.OIDC_GRANT_TYPE_REFRESH_TOKEN,
|
OIDCGrantType.OIDC_GRANT_TYPE_REFRESH_TOKEN,
|
||||||
];
|
];
|
||||||
public oidcAppTypes: OIDCAppType[] = [
|
public oidcAppTypes: OIDCAppType[] = [
|
||||||
@ -274,13 +276,24 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
|||||||
if (this.app.oidcConfig) {
|
if (this.app.oidcConfig) {
|
||||||
this.getAuthMethodOptions('OIDC');
|
this.getAuthMethodOptions('OIDC');
|
||||||
|
|
||||||
this.settingsList = [
|
if (
|
||||||
{ id: 'configuration', i18nKey: 'APP.CONFIGURATION' },
|
this.app.oidcConfig.grantTypesList.length === 1 &&
|
||||||
{ id: 'token', i18nKey: 'APP.TOKEN' },
|
this.app.oidcConfig.grantTypesList[0] === OIDCGrantType.OIDC_GRANT_TYPE_DEVICE_CODE
|
||||||
{ id: 'redirect-uris', i18nKey: 'APP.OIDC.REDIRECTSECTIONTITLE' },
|
) {
|
||||||
{ id: 'additional-origins', i18nKey: 'APP.ADDITIONALORIGINS' },
|
this.settingsList = [
|
||||||
{ id: 'urls', i18nKey: 'APP.URLS' },
|
{ id: 'configuration', i18nKey: 'APP.CONFIGURATION' },
|
||||||
];
|
{ id: 'token', i18nKey: 'APP.TOKEN' },
|
||||||
|
{ id: 'urls', i18nKey: 'APP.URLS' },
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
this.settingsList = [
|
||||||
|
{ id: 'configuration', i18nKey: 'APP.CONFIGURATION' },
|
||||||
|
{ id: 'token', i18nKey: 'APP.TOKEN' },
|
||||||
|
{ id: 'redirect-uris', i18nKey: 'APP.OIDC.REDIRECTSECTIONTITLE' },
|
||||||
|
{ id: 'additional-origins', i18nKey: 'APP.ADDITIONALORIGINS' },
|
||||||
|
{ id: 'urls', i18nKey: 'APP.URLS' },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
this.initialAuthMethod = this.authMethodFromPartialConfig({ oidc: this.app.oidcConfig });
|
this.initialAuthMethod = this.authMethodFromPartialConfig({ oidc: this.app.oidcConfig });
|
||||||
this.currentAuthMethod = this.initialAuthMethod;
|
this.currentAuthMethod = this.initialAuthMethod;
|
||||||
@ -381,7 +394,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
|||||||
if (type === 'OIDC') {
|
if (type === 'OIDC') {
|
||||||
switch (this.app?.oidcConfig?.appType) {
|
switch (this.app?.oidcConfig?.appType) {
|
||||||
case OIDCAppType.OIDC_APP_TYPE_NATIVE:
|
case OIDCAppType.OIDC_APP_TYPE_NATIVE:
|
||||||
this.authMethods = [PKCE_METHOD, CUSTOM_METHOD];
|
this.authMethods = [PKCE_METHOD, DEVICE_CODE_METHOD, CUSTOM_METHOD];
|
||||||
break;
|
break;
|
||||||
case OIDCAppType.OIDC_APP_TYPE_WEB:
|
case OIDCAppType.OIDC_APP_TYPE_WEB:
|
||||||
this.authMethods = [PKCE_METHOD, CODE_METHOD, PK_JWT_METHOD, POST_METHOD];
|
this.authMethods = [PKCE_METHOD, CODE_METHOD, PK_JWT_METHOD, POST_METHOD];
|
||||||
|
@ -16,10 +16,11 @@ export const CODE_METHOD: RadioItemAuthType = {
|
|||||||
prefix: 'CODE',
|
prefix: 'CODE',
|
||||||
background: 'linear-gradient(40deg, rgb(25 105 143) 30%, rgb(23 95 129))',
|
background: 'linear-gradient(40deg, rgb(25 105 143) 30%, rgb(23 95 129))',
|
||||||
responseType: OIDCResponseType.OIDC_RESPONSE_TYPE_CODE,
|
responseType: OIDCResponseType.OIDC_RESPONSE_TYPE_CODE,
|
||||||
grantType: OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE,
|
grantType: [OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE],
|
||||||
authMethod: OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_BASIC,
|
authMethod: OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_BASIC,
|
||||||
recommended: false,
|
recommended: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PKCE_METHOD: RadioItemAuthType = {
|
export const PKCE_METHOD: RadioItemAuthType = {
|
||||||
key: 'PKCE',
|
key: 'PKCE',
|
||||||
titleI18nKey: 'APP.AUTHMETHODS.PKCE.TITLE',
|
titleI18nKey: 'APP.AUTHMETHODS.PKCE.TITLE',
|
||||||
@ -28,10 +29,11 @@ export const PKCE_METHOD: RadioItemAuthType = {
|
|||||||
prefix: 'PKCE',
|
prefix: 'PKCE',
|
||||||
background: 'linear-gradient(40deg, #059669 30%, #047857)',
|
background: 'linear-gradient(40deg, #059669 30%, #047857)',
|
||||||
responseType: OIDCResponseType.OIDC_RESPONSE_TYPE_CODE,
|
responseType: OIDCResponseType.OIDC_RESPONSE_TYPE_CODE,
|
||||||
grantType: OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE,
|
grantType: [OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE],
|
||||||
authMethod: OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE,
|
authMethod: OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE,
|
||||||
recommended: true,
|
recommended: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const POST_METHOD: RadioItemAuthType = {
|
export const POST_METHOD: RadioItemAuthType = {
|
||||||
key: 'POST',
|
key: 'POST',
|
||||||
titleI18nKey: 'APP.AUTHMETHODS.POST.TITLE',
|
titleI18nKey: 'APP.AUTHMETHODS.POST.TITLE',
|
||||||
@ -40,10 +42,11 @@ export const POST_METHOD: RadioItemAuthType = {
|
|||||||
prefix: 'POST',
|
prefix: 'POST',
|
||||||
background: 'linear-gradient(40deg, #c53b3b 30%, rgb(169 51 51))',
|
background: 'linear-gradient(40deg, #c53b3b 30%, rgb(169 51 51))',
|
||||||
responseType: OIDCResponseType.OIDC_RESPONSE_TYPE_CODE,
|
responseType: OIDCResponseType.OIDC_RESPONSE_TYPE_CODE,
|
||||||
grantType: OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE,
|
grantType: [OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE],
|
||||||
authMethod: OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_POST,
|
authMethod: OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_POST,
|
||||||
notRecommended: true,
|
notRecommended: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PK_JWT_METHOD: RadioItemAuthType = {
|
export const PK_JWT_METHOD: RadioItemAuthType = {
|
||||||
key: 'PK_JWT',
|
key: 'PK_JWT',
|
||||||
titleI18nKey: 'APP.AUTHMETHODS.PK_JWT.TITLE',
|
titleI18nKey: 'APP.AUTHMETHODS.PK_JWT.TITLE',
|
||||||
@ -52,11 +55,12 @@ export const PK_JWT_METHOD: RadioItemAuthType = {
|
|||||||
prefix: 'JWT',
|
prefix: 'JWT',
|
||||||
background: 'linear-gradient(40deg, rgb(70 77 145) 30%, rgb(58 65 124))',
|
background: 'linear-gradient(40deg, rgb(70 77 145) 30%, rgb(58 65 124))',
|
||||||
responseType: OIDCResponseType.OIDC_RESPONSE_TYPE_CODE,
|
responseType: OIDCResponseType.OIDC_RESPONSE_TYPE_CODE,
|
||||||
grantType: OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE,
|
grantType: [OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE],
|
||||||
authMethod: OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_PRIVATE_KEY_JWT,
|
authMethod: OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_PRIVATE_KEY_JWT,
|
||||||
apiAuthMethod: APIAuthMethodType.API_AUTH_METHOD_TYPE_PRIVATE_KEY_JWT,
|
apiAuthMethod: APIAuthMethodType.API_AUTH_METHOD_TYPE_PRIVATE_KEY_JWT,
|
||||||
// recommended: true,
|
// recommended: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BASIC_AUTH_METHOD: RadioItemAuthType = {
|
export const BASIC_AUTH_METHOD: RadioItemAuthType = {
|
||||||
key: 'BASIC',
|
key: 'BASIC',
|
||||||
titleI18nKey: 'APP.AUTHMETHODS.BASIC.TITLE',
|
titleI18nKey: 'APP.AUTHMETHODS.BASIC.TITLE',
|
||||||
@ -65,7 +69,7 @@ export const BASIC_AUTH_METHOD: RadioItemAuthType = {
|
|||||||
prefix: 'BASIC',
|
prefix: 'BASIC',
|
||||||
background: 'linear-gradient(40deg, #c53b3b 30%, rgb(169 51 51))',
|
background: 'linear-gradient(40deg, #c53b3b 30%, rgb(169 51 51))',
|
||||||
responseType: OIDCResponseType.OIDC_RESPONSE_TYPE_CODE,
|
responseType: OIDCResponseType.OIDC_RESPONSE_TYPE_CODE,
|
||||||
grantType: OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE,
|
grantType: [OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE],
|
||||||
authMethod: OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_POST,
|
authMethod: OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_POST,
|
||||||
apiAuthMethod: APIAuthMethodType.API_AUTH_METHOD_TYPE_BASIC,
|
apiAuthMethod: APIAuthMethodType.API_AUTH_METHOD_TYPE_BASIC,
|
||||||
};
|
};
|
||||||
@ -78,11 +82,24 @@ export const IMPLICIT_METHOD: RadioItemAuthType = {
|
|||||||
prefix: 'IMP',
|
prefix: 'IMP',
|
||||||
background: 'linear-gradient(40deg, #c53b3b 30%, rgb(169 51 51))',
|
background: 'linear-gradient(40deg, #c53b3b 30%, rgb(169 51 51))',
|
||||||
responseType: OIDCResponseType.OIDC_RESPONSE_TYPE_ID_TOKEN,
|
responseType: OIDCResponseType.OIDC_RESPONSE_TYPE_ID_TOKEN,
|
||||||
grantType: OIDCGrantType.OIDC_GRANT_TYPE_IMPLICIT,
|
grantType: [OIDCGrantType.OIDC_GRANT_TYPE_IMPLICIT],
|
||||||
authMethod: OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE,
|
authMethod: OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE,
|
||||||
notRecommended: true,
|
notRecommended: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const DEVICE_CODE_METHOD: RadioItemAuthType = {
|
||||||
|
key: 'DEVICECODE',
|
||||||
|
titleI18nKey: 'APP.AUTHMETHODS.DEVICECODE.TITLE',
|
||||||
|
descI18nKey: 'APP.AUTHMETHODS.DEVICECODE.DESCRIPTION',
|
||||||
|
disabled: false,
|
||||||
|
prefix: 'DEVICECODE',
|
||||||
|
background: 'linear-gradient(40deg, rgb(56 189 248) 30%, rgb(14 165 233))',
|
||||||
|
responseType: OIDCResponseType.OIDC_RESPONSE_TYPE_CODE,
|
||||||
|
grantType: [OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE, OIDCGrantType.OIDC_GRANT_TYPE_DEVICE_CODE],
|
||||||
|
authMethod: OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_BASIC,
|
||||||
|
recommended: false,
|
||||||
|
};
|
||||||
|
|
||||||
export const CUSTOM_METHOD: RadioItemAuthType = {
|
export const CUSTOM_METHOD: RadioItemAuthType = {
|
||||||
key: 'CUSTOM',
|
key: 'CUSTOM',
|
||||||
titleI18nKey: 'APP.AUTHMETHODS.CUSTOM.TITLE',
|
titleI18nKey: 'APP.AUTHMETHODS.CUSTOM.TITLE',
|
||||||
@ -112,6 +129,15 @@ export function getPartialConfigFromAuthMethod(authMethod: string):
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
return config;
|
return config;
|
||||||
|
case DEVICE_CODE_METHOD.key:
|
||||||
|
config = {
|
||||||
|
oidc: {
|
||||||
|
responseTypesList: [OIDCResponseType.OIDC_RESPONSE_TYPE_CODE],
|
||||||
|
grantTypesList: [OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE, OIDCGrantType.OIDC_GRANT_TYPE_DEVICE_CODE],
|
||||||
|
authMethodType: OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return config;
|
||||||
case PKCE_METHOD.key:
|
case PKCE_METHOD.key:
|
||||||
config = {
|
config = {
|
||||||
oidc: {
|
oidc: {
|
||||||
@ -211,6 +237,38 @@ export function getAuthMethodFromPartialConfig(config: {
|
|||||||
OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_POST,
|
OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_POST,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const deviceCode = JSON.stringify([
|
||||||
|
[OIDCResponseType.OIDC_RESPONSE_TYPE_CODE],
|
||||||
|
[OIDCGrantType.OIDC_GRANT_TYPE_DEVICE_CODE],
|
||||||
|
OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const deviceCodeWithCode = 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,
|
||||||
|
],
|
||||||
|
OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const deviceCodeWithCodeAndRefresh = 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,
|
||||||
|
],
|
||||||
|
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],
|
||||||
|
OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE,
|
||||||
|
]);
|
||||||
|
|
||||||
const pkjwt = JSON.stringify([
|
const pkjwt = JSON.stringify([
|
||||||
[OIDCResponseType.OIDC_RESPONSE_TYPE_CODE],
|
[OIDCResponseType.OIDC_RESPONSE_TYPE_CODE],
|
||||||
[OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE],
|
[OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE],
|
||||||
@ -245,6 +303,15 @@ export function getAuthMethodFromPartialConfig(config: {
|
|||||||
case postWithRefresh:
|
case postWithRefresh:
|
||||||
return POST_METHOD.key;
|
return POST_METHOD.key;
|
||||||
|
|
||||||
|
case deviceCode:
|
||||||
|
return DEVICE_CODE_METHOD.key;
|
||||||
|
case deviceCodeWithCode:
|
||||||
|
return DEVICE_CODE_METHOD.key;
|
||||||
|
case deviceCodeWithRefresh:
|
||||||
|
return DEVICE_CODE_METHOD.key;
|
||||||
|
case deviceCodeWithCodeAndRefresh:
|
||||||
|
return DEVICE_CODE_METHOD.key;
|
||||||
|
|
||||||
case pkjwt:
|
case pkjwt:
|
||||||
return PK_JWT_METHOD.key;
|
return PK_JWT_METHOD.key;
|
||||||
case pkjwtWithRefresh:
|
case pkjwtWithRefresh:
|
||||||
|
@ -1965,7 +1965,8 @@
|
|||||||
"GRANT": {
|
"GRANT": {
|
||||||
"0": "Authorization Code",
|
"0": "Authorization Code",
|
||||||
"1": "Implicit",
|
"1": "Implicit",
|
||||||
"2": "Refresh Token"
|
"2": "Refresh Token",
|
||||||
|
"3": "Device Code"
|
||||||
},
|
},
|
||||||
"AUTHMETHOD": {
|
"AUTHMETHOD": {
|
||||||
"0": "Basic",
|
"0": "Basic",
|
||||||
@ -2056,6 +2057,10 @@
|
|||||||
"TITLE": "Implicit",
|
"TITLE": "Implicit",
|
||||||
"DESCRIPTION": "Erhalte die Token direkt vom authorize Endpoint"
|
"DESCRIPTION": "Erhalte die Token direkt vom authorize Endpoint"
|
||||||
},
|
},
|
||||||
|
"DEVICECODE": {
|
||||||
|
"TITLE": "Device Code",
|
||||||
|
"DESCRIPTION": "Autorisieren Sie das Gerät auf einem Computer oder Smartphone."
|
||||||
|
},
|
||||||
"CUSTOM": {
|
"CUSTOM": {
|
||||||
"TITLE": "Custom",
|
"TITLE": "Custom",
|
||||||
"DESCRIPTION": "Deine Konfiguration entspricht keiner anderen Option."
|
"DESCRIPTION": "Deine Konfiguration entspricht keiner anderen Option."
|
||||||
|
@ -1962,7 +1962,8 @@
|
|||||||
"GRANT": {
|
"GRANT": {
|
||||||
"0": "Authorization Code",
|
"0": "Authorization Code",
|
||||||
"1": "Implicit",
|
"1": "Implicit",
|
||||||
"2": "Refresh Token"
|
"2": "Refresh Token",
|
||||||
|
"3": "Device Code"
|
||||||
},
|
},
|
||||||
"AUTHMETHOD": {
|
"AUTHMETHOD": {
|
||||||
"0": "Basic",
|
"0": "Basic",
|
||||||
@ -2053,6 +2054,10 @@
|
|||||||
"TITLE": "Implicit",
|
"TITLE": "Implicit",
|
||||||
"DESCRIPTION": "Get the tokens directly from the authorization endpoint"
|
"DESCRIPTION": "Get the tokens directly from the authorization endpoint"
|
||||||
},
|
},
|
||||||
|
"DEVICECODE": {
|
||||||
|
"TITLE": "Device Code",
|
||||||
|
"DESCRIPTION": "Authorize the device on a computer or smartphone."
|
||||||
|
},
|
||||||
"CUSTOM": {
|
"CUSTOM": {
|
||||||
"TITLE": "Custom",
|
"TITLE": "Custom",
|
||||||
"DESCRIPTION": "Your setting doesn't correspond to any other option."
|
"DESCRIPTION": "Your setting doesn't correspond to any other option."
|
||||||
|
@ -1962,7 +1962,8 @@
|
|||||||
"GRANT": {
|
"GRANT": {
|
||||||
"0": "Código de autorización",
|
"0": "Código de autorización",
|
||||||
"1": "Implícito",
|
"1": "Implícito",
|
||||||
"2": "Token de refresco"
|
"2": "Token de refresco",
|
||||||
|
"3": "Device Code"
|
||||||
},
|
},
|
||||||
"AUTHMETHOD": {
|
"AUTHMETHOD": {
|
||||||
"0": "Básico",
|
"0": "Básico",
|
||||||
@ -2053,6 +2054,10 @@
|
|||||||
"TITLE": "Implícita",
|
"TITLE": "Implícita",
|
||||||
"DESCRIPTION": "Obtén los tokens directamente del endpoint de autorización"
|
"DESCRIPTION": "Obtén los tokens directamente del endpoint de autorización"
|
||||||
},
|
},
|
||||||
|
"DEVICECODE": {
|
||||||
|
"TITLE": "Device Code",
|
||||||
|
"DESCRIPTION": "Autorizar el dispositivo en una computadora o teléfono."
|
||||||
|
},
|
||||||
"CUSTOM": {
|
"CUSTOM": {
|
||||||
"TITLE": "Personalizada",
|
"TITLE": "Personalizada",
|
||||||
"DESCRIPTION": "Tu configuración no se corresponde con alguna de las otras opciones."
|
"DESCRIPTION": "Tu configuración no se corresponde con alguna de las otras opciones."
|
||||||
|
@ -1966,7 +1966,8 @@
|
|||||||
"GRANT": {
|
"GRANT": {
|
||||||
"0": "Code d'autorisation",
|
"0": "Code d'autorisation",
|
||||||
"1": "Implicite",
|
"1": "Implicite",
|
||||||
"2": "Rafraîchir le jeton"
|
"2": "Rafraîchir le jeton",
|
||||||
|
"3": "Device Code"
|
||||||
},
|
},
|
||||||
"AUTHMETHOD": {
|
"AUTHMETHOD": {
|
||||||
"0": "Basic",
|
"0": "Basic",
|
||||||
@ -2045,6 +2046,10 @@
|
|||||||
"TITLE": "Implicite",
|
"TITLE": "Implicite",
|
||||||
"DESCRIPTION": "Obtenir les jetons directement à partir du point final d'autorisation"
|
"DESCRIPTION": "Obtenir les jetons directement à partir du point final d'autorisation"
|
||||||
},
|
},
|
||||||
|
"DEVICECODE": {
|
||||||
|
"TITLE": "Device Code",
|
||||||
|
"DESCRIPTION": "Autoriser l'appareil sur un ordinateur ou un smartphone."
|
||||||
|
},
|
||||||
"CUSTOM": {
|
"CUSTOM": {
|
||||||
"TITLE": "Personnalisé",
|
"TITLE": "Personnalisé",
|
||||||
"DESCRIPTION": "Votre paramètre ne correspond à aucune autre option."
|
"DESCRIPTION": "Votre paramètre ne correspond à aucune autre option."
|
||||||
|
@ -1967,7 +1967,8 @@
|
|||||||
"GRANT": {
|
"GRANT": {
|
||||||
"0": "Authorization Code",
|
"0": "Authorization Code",
|
||||||
"1": "Implicit",
|
"1": "Implicit",
|
||||||
"2": "Refresh Token"
|
"2": "Refresh Token",
|
||||||
|
"3": "Device Code"
|
||||||
},
|
},
|
||||||
"AUTHMETHOD": {
|
"AUTHMETHOD": {
|
||||||
"0": "Basic",
|
"0": "Basic",
|
||||||
@ -2058,6 +2059,10 @@
|
|||||||
"TITLE": "Implicit",
|
"TITLE": "Implicit",
|
||||||
"DESCRIPTION": "Ottenere i token direttamente dall'endpoint di autorizzazione"
|
"DESCRIPTION": "Ottenere i token direttamente dall'endpoint di autorizzazione"
|
||||||
},
|
},
|
||||||
|
"DEVICECODE": {
|
||||||
|
"TITLE": "Device Code",
|
||||||
|
"DESCRIPTION": "Autorizza il dispositivo su un computer o uno smartphone."
|
||||||
|
},
|
||||||
"CUSTOM": {
|
"CUSTOM": {
|
||||||
"TITLE": "Custom",
|
"TITLE": "Custom",
|
||||||
"DESCRIPTION": "La tua impostazione non corrisponde a nessun'altra opzione."
|
"DESCRIPTION": "La tua impostazione non corrisponde a nessun'altra opzione."
|
||||||
|
@ -1957,7 +1957,8 @@
|
|||||||
"GRANT": {
|
"GRANT": {
|
||||||
"0": "Authorization Code",
|
"0": "Authorization Code",
|
||||||
"1": "Implicit",
|
"1": "Implicit",
|
||||||
"2": "Refresh Token"
|
"2": "Refresh Token",
|
||||||
|
"3": "Device Code"
|
||||||
},
|
},
|
||||||
"AUTHMETHOD": {
|
"AUTHMETHOD": {
|
||||||
"0": "Basic",
|
"0": "Basic",
|
||||||
@ -2048,6 +2049,10 @@
|
|||||||
"TITLE": "Implicit",
|
"TITLE": "Implicit",
|
||||||
"DESCRIPTION": "認証エンドポイントから直接トークンを取得します。"
|
"DESCRIPTION": "認証エンドポイントから直接トークンを取得します。"
|
||||||
},
|
},
|
||||||
|
"DEVICECODE": {
|
||||||
|
"TITLE": "Device Code",
|
||||||
|
"DESCRIPTION": "コンピューターまたはスマートフォンでデバイスを認証します。"
|
||||||
|
},
|
||||||
"CUSTOM": {
|
"CUSTOM": {
|
||||||
"TITLE": "Custom",
|
"TITLE": "Custom",
|
||||||
"DESCRIPTION": "設定は他のオプションに対応していません。"
|
"DESCRIPTION": "設定は他のオプションに対応していません。"
|
||||||
|
@ -1966,7 +1966,8 @@
|
|||||||
"GRANT": {
|
"GRANT": {
|
||||||
"0": "Kod autoryzacyjny",
|
"0": "Kod autoryzacyjny",
|
||||||
"1": "Implicite",
|
"1": "Implicite",
|
||||||
"2": "Token odświeżający"
|
"2": "Token odświeżający",
|
||||||
|
"3": "Device Code"
|
||||||
},
|
},
|
||||||
"AUTHMETHOD": {
|
"AUTHMETHOD": {
|
||||||
"0": "Podstawowy",
|
"0": "Podstawowy",
|
||||||
@ -2057,6 +2058,10 @@
|
|||||||
"TITLE": "Implicit",
|
"TITLE": "Implicit",
|
||||||
"DESCRIPTION": "Pobierz tokeny bezpośrednio z punktu autoryzacyjnego"
|
"DESCRIPTION": "Pobierz tokeny bezpośrednio z punktu autoryzacyjnego"
|
||||||
},
|
},
|
||||||
|
"DEVICECODE": {
|
||||||
|
"TITLE": "Device Code",
|
||||||
|
"DESCRIPTION": "Autoryzuj urządzenie na komputerze lub smartfonie."
|
||||||
|
},
|
||||||
"CUSTOM": {
|
"CUSTOM": {
|
||||||
"TITLE": "Niestandardowy",
|
"TITLE": "Niestandardowy",
|
||||||
"DESCRIPTION": "Twoje ustawienie nie odpowiada żadnej innej opcji."
|
"DESCRIPTION": "Twoje ustawienie nie odpowiada żadnej innej opcji."
|
||||||
|
@ -1965,7 +1965,8 @@
|
|||||||
"GRANT": {
|
"GRANT": {
|
||||||
"0": "Authorization Code",
|
"0": "Authorization Code",
|
||||||
"1": "Implicit",
|
"1": "Implicit",
|
||||||
"2": "Refresh Token"
|
"2": "Refresh Token",
|
||||||
|
"3": "Device Code"
|
||||||
},
|
},
|
||||||
"AUTHMETHOD": {
|
"AUTHMETHOD": {
|
||||||
"0": "Basic",
|
"0": "Basic",
|
||||||
@ -2044,6 +2045,10 @@
|
|||||||
"TITLE": "Implicit",
|
"TITLE": "Implicit",
|
||||||
"DESCRIPTION": "直接从授权端点获取令牌"
|
"DESCRIPTION": "直接从授权端点获取令牌"
|
||||||
},
|
},
|
||||||
|
"DEVICECODE": {
|
||||||
|
"TITLE": "Device Code",
|
||||||
|
"DESCRIPTION": "在计算机或智能手机上授权设备。"
|
||||||
|
},
|
||||||
"CUSTOM": {
|
"CUSTOM": {
|
||||||
"TITLE": "Custom",
|
"TITLE": "Custom",
|
||||||
"DESCRIPTION": "您的设置与任何其他选项都不对应。"
|
"DESCRIPTION": "您的设置与任何其他选项都不对应。"
|
||||||
|
@ -2,7 +2,8 @@ import { Apps, ensureProjectExists, ensureProjectResourceDoesntExist } from '../
|
|||||||
import { Context } from 'support/commands';
|
import { Context } from 'support/commands';
|
||||||
|
|
||||||
const testProjectName = 'e2eprojectapplication';
|
const testProjectName = 'e2eprojectapplication';
|
||||||
const testAppName = 'e2eappundertest';
|
const testPKCEAppName = 'e2eapppkcetest';
|
||||||
|
const testDEVICECODEAppName = 'e2eappdevicecodetest';
|
||||||
|
|
||||||
describe('applications', () => {
|
describe('applications', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -17,15 +18,15 @@ describe('applications', () => {
|
|||||||
beforeEach(`ensure it doesn't exist already`, () => {
|
beforeEach(`ensure it doesn't exist already`, () => {
|
||||||
cy.get<Context>('@ctx').then((ctx) => {
|
cy.get<Context>('@ctx').then((ctx) => {
|
||||||
cy.get<string>('@projectId').then((projectId) => {
|
cy.get<string>('@projectId').then((projectId) => {
|
||||||
ensureProjectResourceDoesntExist(ctx.api, projectId, Apps, testAppName);
|
ensureProjectResourceDoesntExist(ctx.api, projectId, Apps, testPKCEAppName);
|
||||||
cy.visit(`/projects/${projectId}`);
|
cy.visit(`/projects/${projectId}`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('add app', () => {
|
it('add web pkce app', () => {
|
||||||
cy.get('[data-e2e="app-card-add"]').should('be.visible').click();
|
cy.get('[data-e2e="app-card-add"]').should('be.visible').click();
|
||||||
cy.get('[formcontrolname="name"]').focus().type(testAppName);
|
cy.get('[formcontrolname="name"]').focus().type(testPKCEAppName);
|
||||||
cy.get('[for="WEB"]').click();
|
cy.get('[for="WEB"]').click();
|
||||||
cy.get('[data-e2e="continue-button-nameandtype"]').click();
|
cy.get('[data-e2e="continue-button-nameandtype"]').click();
|
||||||
cy.get('[for="PKCE"]').should('be.visible').click();
|
cy.get('[for="PKCE"]').should('be.visible').click();
|
||||||
@ -43,6 +44,33 @@ describe('applications', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('add native device code app', () => {
|
||||||
|
beforeEach(`ensure it doesn't exist already`, () => {
|
||||||
|
cy.get<Context>('@ctx').then((ctx) => {
|
||||||
|
cy.get<string>('@projectId').then((projectId) => {
|
||||||
|
ensureProjectResourceDoesntExist(ctx.api, projectId, Apps, testDEVICECODEAppName);
|
||||||
|
cy.visit(`/projects/${projectId}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('add device code app', () => {
|
||||||
|
cy.get('[data-e2e="app-card-add"]').should('be.visible').click();
|
||||||
|
cy.get('[formcontrolname="name"]').focus().type(testDEVICECODEAppName);
|
||||||
|
cy.get('[for="N"]').click();
|
||||||
|
cy.get('[data-e2e="continue-button-nameandtype"]').click();
|
||||||
|
cy.get('[for="DEVICECODE"]').should('be.visible').click();
|
||||||
|
cy.get('[data-e2e="continue-button-authmethod"]').click();
|
||||||
|
cy.get('[data-e2e="create-button"]').click();
|
||||||
|
cy.get('[id*=overlay]').should('exist');
|
||||||
|
cy.shouldConfirmSuccess();
|
||||||
|
const expectClientId = new RegExp(`^.*[0-9]+\\@${testProjectName}.*$`);
|
||||||
|
cy.get('[data-e2e="client-id-copy"]').click();
|
||||||
|
cy.contains('[data-e2e="client-id"]', expectClientId);
|
||||||
|
cy.clipboardMatches(expectClientId);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('edit app', () => {
|
describe('edit app', () => {
|
||||||
it('should configure an application to enable dev mode');
|
it('should configure an application to enable dev mode');
|
||||||
it('should configure an application to put user roles and info inside id token');
|
it('should configure an application to put user roles and info inside id token');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user