mirror of
https://github.com/zitadel/zitadel.git
synced 2025-03-01 17:17:25 +00:00
feat: allow skip of success page for native apps (#5627)
add possibility to return to callback directly after login without rendering the successful login page
This commit is contained in:
parent
991a56341b
commit
d25454b84b
@ -305,7 +305,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<span class="right">
|
<span class="right">
|
||||||
<span>
|
<span>
|
||||||
{{ 'APP.API.AUTHMETHOD.' + authMethodType?.value | translate }}
|
{{ 'APP.API.AUTHMETHOD.' + apiAppRequest.toObject().authMethodType | translate }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -331,11 +331,24 @@
|
|||||||
</div>
|
</div>
|
||||||
</cnsl-info-section>
|
</cnsl-info-section>
|
||||||
|
|
||||||
|
<mat-checkbox
|
||||||
|
*ngIf="skipNativeAppSuccessPage && appType?.value === OIDCAppType.OIDC_APP_TYPE_NATIVE"
|
||||||
|
class="full-width"
|
||||||
|
style="margin-top: 1.5rem"
|
||||||
|
[formControl]="skipNativeAppSuccessPage"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
{{ 'APP.OIDC.SKIPNATIVEAPPSUCCESSPAGE' | translate }}</mat-checkbox
|
||||||
|
>
|
||||||
|
<cnsl-info-section *ngIf="appType?.value === OIDCAppType.OIDC_APP_TYPE_NATIVE" class="full-width app-desc">
|
||||||
|
<span>{{ 'APP.OIDC.SKIPNATIVEAPPSUCCESSPAGE_DESCRIPTION' | translate }}</span>
|
||||||
|
</cnsl-info-section>
|
||||||
|
|
||||||
<cnsl-redirect-uris
|
<cnsl-redirect-uris
|
||||||
*ngIf="appType?.value !== undefined"
|
*ngIf="appType?.value !== undefined"
|
||||||
class="redirect-section"
|
class="redirect-section"
|
||||||
[disabled]="!canWrite"
|
[disabled]="!canWrite"
|
||||||
[devMode]="devMode?.value"
|
[devMode]="!!devMode?.value"
|
||||||
[(ngModel)]="redirectUrisList"
|
[(ngModel)]="redirectUrisList"
|
||||||
title="{{ 'APP.OIDC.REDIRECT' | translate }}"
|
title="{{ 'APP.OIDC.REDIRECT' | translate }}"
|
||||||
[isNative]="appType?.value === OIDCAppType.OIDC_APP_TYPE_NATIVE"
|
[isNative]="appType?.value === OIDCAppType.OIDC_APP_TYPE_NATIVE"
|
||||||
@ -346,7 +359,7 @@
|
|||||||
*ngIf="appType?.value !== undefined"
|
*ngIf="appType?.value !== undefined"
|
||||||
class="redirect-section"
|
class="redirect-section"
|
||||||
[disabled]="!canWrite"
|
[disabled]="!canWrite"
|
||||||
[devMode]="devMode?.value"
|
[devMode]="!!devMode?.value"
|
||||||
[(ngModel)]="postLogoutRedirectUrisList"
|
[(ngModel)]="postLogoutRedirectUrisList"
|
||||||
title="{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}"
|
title="{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}"
|
||||||
[isNative]="appType?.value === OIDCAppType.OIDC_APP_TYPE_NATIVE"
|
[isNative]="appType?.value === OIDCAppType.OIDC_APP_TYPE_NATIVE"
|
||||||
|
@ -2,7 +2,7 @@ import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
|||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { AbstractControl, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
import { AbstractControl, FormControl, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||||
import { MatLegacyCheckboxChange as MatCheckboxChange } from '@angular/material/legacy-checkbox';
|
import { MatLegacyCheckboxChange as MatCheckboxChange } from '@angular/material/legacy-checkbox';
|
||||||
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
|
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
@ -149,7 +149,8 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
|||||||
private http: HttpClient,
|
private http: HttpClient,
|
||||||
) {
|
) {
|
||||||
this.oidcForm = this.fb.group({
|
this.oidcForm = this.fb.group({
|
||||||
devMode: [{ value: false, disabled: true }, []],
|
devMode: [{ value: false, disabled: true }],
|
||||||
|
skipNativeAppSuccessPage: [{ value: false, disabled: true }],
|
||||||
clientId: [{ value: '', disabled: true }],
|
clientId: [{ value: '', disabled: true }],
|
||||||
responseTypesList: [{ value: [], disabled: true }],
|
responseTypesList: [{ value: [], disabled: true }],
|
||||||
grantTypesList: [{ value: [], disabled: true }],
|
grantTypesList: [{ value: [], disabled: true }],
|
||||||
@ -548,7 +549,8 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
|||||||
this.app.oidcConfig.redirectUrisList = this.redirectUrisList;
|
this.app.oidcConfig.redirectUrisList = this.redirectUrisList;
|
||||||
this.app.oidcConfig.postLogoutRedirectUrisList = this.postLogoutRedirectUrisList;
|
this.app.oidcConfig.postLogoutRedirectUrisList = this.postLogoutRedirectUrisList;
|
||||||
this.app.oidcConfig.additionalOriginsList = this.additionalOriginsList;
|
this.app.oidcConfig.additionalOriginsList = this.additionalOriginsList;
|
||||||
this.app.oidcConfig.devMode = this.devMode?.value;
|
this.app.oidcConfig.devMode = !!this.devMode?.value;
|
||||||
|
this.app.oidcConfig.skipNativeAppSuccessPage = !!this.skipNativeAppSuccessPage?.value;
|
||||||
|
|
||||||
const req = new UpdateOIDCAppConfigRequest();
|
const req = new UpdateOIDCAppConfigRequest();
|
||||||
req.setProjectId(this.projectId);
|
req.setProjectId(this.projectId);
|
||||||
@ -571,6 +573,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
|||||||
req.setAdditionalOriginsList(this.app.oidcConfig.additionalOriginsList);
|
req.setAdditionalOriginsList(this.app.oidcConfig.additionalOriginsList);
|
||||||
req.setPostLogoutRedirectUrisList(this.app.oidcConfig.postLogoutRedirectUrisList);
|
req.setPostLogoutRedirectUrisList(this.app.oidcConfig.postLogoutRedirectUrisList);
|
||||||
req.setDevMode(this.app.oidcConfig.devMode);
|
req.setDevMode(this.app.oidcConfig.devMode);
|
||||||
|
req.setSkipNativeAppSuccessPage(this.app.oidcConfig.skipNativeAppSuccessPage);
|
||||||
|
|
||||||
if (this.clockSkewSeconds?.value) {
|
if (this.clockSkewSeconds?.value) {
|
||||||
const dur = new Duration();
|
const dur = new Duration();
|
||||||
@ -738,11 +741,15 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public get apiAuthMethodType(): AbstractControl | null {
|
public get apiAuthMethodType(): AbstractControl | null {
|
||||||
return this.apiForm.get('authMethodType');
|
return this.apiForm.get('authMethodType') as UntypedFormControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get devMode(): UntypedFormControl | null {
|
public get devMode(): FormControl<boolean> | null {
|
||||||
return this.oidcForm.get('devMode') as UntypedFormControl;
|
return this.oidcForm.get('devMode') as FormControl<boolean>;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get skipNativeAppSuccessPage(): FormControl<boolean> | null {
|
||||||
|
return this.oidcForm.get('skipNativeAppSuccessPage') as FormControl<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get accessTokenType(): AbstractControl | null {
|
public get accessTokenType(): AbstractControl | null {
|
||||||
|
@ -1930,6 +1930,8 @@
|
|||||||
"REGENERATESECRET": "Client Secret neu generieren",
|
"REGENERATESECRET": "Client Secret neu generieren",
|
||||||
"DEVMODE": "Entwicklermodus",
|
"DEVMODE": "Entwicklermodus",
|
||||||
"DEVMODEDESC": "Bei eingeschaltetem Entwicklermodus werden die Weiterleitungs-URIs im OIDC-Flow nicht validiert.",
|
"DEVMODEDESC": "Bei eingeschaltetem Entwicklermodus werden die Weiterleitungs-URIs im OIDC-Flow nicht validiert.",
|
||||||
|
"SKIPNATIVEAPPSUCCESSPAGE": "Login Erfolgseite überspringen",
|
||||||
|
"SKIPNATIVEAPPSUCCESSPAGE_DESCRIPTION": "Erfolgseite nach dem Login für diese Native Applikation überspringen.",
|
||||||
"REDIRECT": "Weiterleitungs-URIs",
|
"REDIRECT": "Weiterleitungs-URIs",
|
||||||
"REDIRECTSECTION": "Weiterleitungs-URIs",
|
"REDIRECTSECTION": "Weiterleitungs-URIs",
|
||||||
"POSTLOGOUTREDIRECT": "URIs für Post-Log-out",
|
"POSTLOGOUTREDIRECT": "URIs für Post-Log-out",
|
||||||
|
@ -1923,6 +1923,8 @@
|
|||||||
"REGENERATESECRET": "Regenerate Client Secret",
|
"REGENERATESECRET": "Regenerate Client Secret",
|
||||||
"DEVMODE": "Development Mode",
|
"DEVMODE": "Development Mode",
|
||||||
"DEVMODEDESC": "Beware: With development mode enabled redirect URIs will not be validated.",
|
"DEVMODEDESC": "Beware: With development mode enabled redirect URIs will not be validated.",
|
||||||
|
"SKIPNATIVEAPPSUCCESSPAGE": "Skip Login Success Page",
|
||||||
|
"SKIPNATIVEAPPSUCCESSPAGE_DESCRIPTION": "Skip the success page after a login for this native app.",
|
||||||
"REDIRECT": "Redirect URIs",
|
"REDIRECT": "Redirect URIs",
|
||||||
"REDIRECTSECTION": "Redirect URIs",
|
"REDIRECTSECTION": "Redirect URIs",
|
||||||
"POSTLOGOUTREDIRECT": "Post Logout URIs",
|
"POSTLOGOUTREDIRECT": "Post Logout URIs",
|
||||||
|
@ -1931,6 +1931,8 @@
|
|||||||
"REGENERATESECRET": "Régénérer le secret du client",
|
"REGENERATESECRET": "Régénérer le secret du client",
|
||||||
"DEVMODE": "Mode développement",
|
"DEVMODE": "Mode développement",
|
||||||
"DEVMODEDESC": "Attention",
|
"DEVMODEDESC": "Attention",
|
||||||
|
"SKIPNATIVEAPPSUCCESSPAGE": "Sauter la page de succès de connexion",
|
||||||
|
"SKIPNATIVEAPPSUCCESSPAGE_DESCRIPTION": "Sauter la page de succès après la connexion pour cette application native",
|
||||||
"REDIRECT": "Rediriger les URI",
|
"REDIRECT": "Rediriger les URI",
|
||||||
"REDIRECTSECTION": "URI de redirection",
|
"REDIRECTSECTION": "URI de redirection",
|
||||||
"POSTLOGOUTREDIRECT": "URIs de post-déconnexion",
|
"POSTLOGOUTREDIRECT": "URIs de post-déconnexion",
|
||||||
|
@ -1932,6 +1932,8 @@
|
|||||||
"REGENERATESECRET": "Rigenera il Client Secret",
|
"REGENERATESECRET": "Rigenera il Client Secret",
|
||||||
"DEVMODE": "Modalit\u00e0 di sviluppo (DEV Mode)",
|
"DEVMODE": "Modalit\u00e0 di sviluppo (DEV Mode)",
|
||||||
"DEVMODEDESC": "Attenzione: Con la modalit\u00e0 di sviluppo abilitata, gli URI di reindirizzamento non saranno convalidati.",
|
"DEVMODEDESC": "Attenzione: Con la modalit\u00e0 di sviluppo abilitata, gli URI di reindirizzamento non saranno convalidati.",
|
||||||
|
"SKIPNATIVEAPPSUCCESSPAGE": "Salta la pagina di successo dopo il login",
|
||||||
|
"SKIPNATIVEAPPSUCCESSPAGE_DESCRIPTION": "Salta la pagina di successo dopo il login per questa applicazione nativa",
|
||||||
"REDIRECT": "URI per il reindrizzamento",
|
"REDIRECT": "URI per il reindrizzamento",
|
||||||
"REDIRECTSECTION": "Reindirizzamento",
|
"REDIRECTSECTION": "Reindirizzamento",
|
||||||
"POSTLOGOUTREDIRECT": "URI post logout",
|
"POSTLOGOUTREDIRECT": "URI post logout",
|
||||||
|
@ -1922,6 +1922,8 @@
|
|||||||
"REGENERATESECRET": "クライアントシークレットを再生成する",
|
"REGENERATESECRET": "クライアントシークレットを再生成する",
|
||||||
"DEVMODE": "開発モード",
|
"DEVMODE": "開発モード",
|
||||||
"DEVMODEDESC": "注意:開発モードを有効にすると、URIが認証されません。",
|
"DEVMODEDESC": "注意:開発モードを有効にすると、URIが認証されません。",
|
||||||
|
"SKIPNATIVEAPPSUCCESSPAGE": "ログイン後に成功ページをスキップする",
|
||||||
|
"SKIPNATIVEAPPSUCCESSPAGE_DESCRIPTION": "このネイティブアプリのログイン後に成功ページをスキップする",
|
||||||
"REDIRECT": "リダイレクトURI",
|
"REDIRECT": "リダイレクトURI",
|
||||||
"REDIRECTSECTION": "リダイレクトURI",
|
"REDIRECTSECTION": "リダイレクトURI",
|
||||||
"POSTLOGOUTREDIRECT": "ログアウトURI",
|
"POSTLOGOUTREDIRECT": "ログアウトURI",
|
||||||
|
@ -1931,6 +1931,8 @@
|
|||||||
"REGENERATESECRET": "Odtwórz sekret klienta",
|
"REGENERATESECRET": "Odtwórz sekret klienta",
|
||||||
"DEVMODE": "Tryb rozwoju",
|
"DEVMODE": "Tryb rozwoju",
|
||||||
"DEVMODEDESC": "Uwaga: przy włączonym trybie rozwoju adresy URI przekierowania nie będą sprawdzane.",
|
"DEVMODEDESC": "Uwaga: przy włączonym trybie rozwoju adresy URI przekierowania nie będą sprawdzane.",
|
||||||
|
"SKIPNATIVEAPPSUCCESSPAGE": "Pomiń stronę sukcesu po zalogowaniu",
|
||||||
|
"SKIPNATIVEAPPSUCCESSPAGE_DESCRIPTION": "Pomiń stronę sukcesu po zalogowaniu dla tej Natywny aplikację",
|
||||||
"REDIRECT": "Adresy URI przekierowania",
|
"REDIRECT": "Adresy URI przekierowania",
|
||||||
"REDIRECTSECTION": "Adresy URI przekierowania",
|
"REDIRECTSECTION": "Adresy URI przekierowania",
|
||||||
"POSTLOGOUTREDIRECT": "Adresy URI po wylogowaniu",
|
"POSTLOGOUTREDIRECT": "Adresy URI po wylogowaniu",
|
||||||
|
@ -1930,6 +1930,8 @@
|
|||||||
"REGENERATESECRET": "重新生成客户端密钥",
|
"REGENERATESECRET": "重新生成客户端密钥",
|
||||||
"DEVMODE": "开发模式",
|
"DEVMODE": "开发模式",
|
||||||
"DEVMODEDESC": "注意:启用开发模式的重定向 URI 将不会被验证。",
|
"DEVMODEDESC": "注意:启用开发模式的重定向 URI 将不会被验证。",
|
||||||
|
"SKIPNATIVEAPPSUCCESSPAGE": "登录后跳过成功页面",
|
||||||
|
"SKIPNATIVEAPPSUCCESSPAGE_DESCRIPTION": "登录后跳过本机应用的成功页面",
|
||||||
"REDIRECT": "重定向 URLs",
|
"REDIRECT": "重定向 URLs",
|
||||||
"REDIRECTSECTION": "重定向 URLs",
|
"REDIRECTSECTION": "重定向 URLs",
|
||||||
"POSTLOGOUTREDIRECT": "退出登录重定向 URLs",
|
"POSTLOGOUTREDIRECT": "退出登录重定向 URLs",
|
||||||
|
@ -142,6 +142,7 @@ On the bottom you can optionally set a **ClockSkew** time which is added to the
|
|||||||
|
|
||||||
Like on creation, you can modify you redirect settings here.
|
Like on creation, you can modify you redirect settings here.
|
||||||
Note that for local development you most likely have to enable development mode, as redirects to http:// are otherwise blocked.
|
Note that for local development you most likely have to enable development mode, as redirects to http:// are otherwise blocked.
|
||||||
|
On Native Apps you can also skip the Login Success Page.
|
||||||
|
|
||||||
<img
|
<img
|
||||||
alt="Redirect URIs"
|
alt="Redirect URIs"
|
||||||
|
@ -800,6 +800,7 @@ func (s *Server) getProjectsAndApps(ctx context.Context, org string) ([]*v1_pb.D
|
|||||||
IdTokenUserinfoAssertion: app.OIDCConfig.AssertIDTokenUserinfo,
|
IdTokenUserinfoAssertion: app.OIDCConfig.AssertIDTokenUserinfo,
|
||||||
ClockSkew: durationpb.New(app.OIDCConfig.ClockSkew),
|
ClockSkew: durationpb.New(app.OIDCConfig.ClockSkew),
|
||||||
AdditionalOrigins: app.OIDCConfig.AdditionalOrigins,
|
AdditionalOrigins: app.OIDCConfig.AdditionalOrigins,
|
||||||
|
SkipNativeAppSuccessPage: app.OIDCConfig.SkipNativeAppSuccessPage,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,7 @@ func AddOIDCAppRequestToDomain(req *mgmt_pb.AddOIDCAppRequest) *domain.OIDCApp {
|
|||||||
IDTokenUserinfoAssertion: req.IdTokenUserinfoAssertion,
|
IDTokenUserinfoAssertion: req.IdTokenUserinfoAssertion,
|
||||||
ClockSkew: req.ClockSkew.AsDuration(),
|
ClockSkew: req.ClockSkew.AsDuration(),
|
||||||
AdditionalOrigins: req.AdditionalOrigins,
|
AdditionalOrigins: req.AdditionalOrigins,
|
||||||
|
SkipNativeAppSuccessPage: req.SkipNativeAppSuccessPage,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,6 +107,7 @@ func UpdateOIDCAppConfigRequestToDomain(app *mgmt_pb.UpdateOIDCAppConfigRequest)
|
|||||||
IDTokenUserinfoAssertion: app.IdTokenUserinfoAssertion,
|
IDTokenUserinfoAssertion: app.IdTokenUserinfoAssertion,
|
||||||
ClockSkew: app.ClockSkew.AsDuration(),
|
ClockSkew: app.ClockSkew.AsDuration(),
|
||||||
AdditionalOrigins: app.AdditionalOrigins,
|
AdditionalOrigins: app.AdditionalOrigins,
|
||||||
|
SkipNativeAppSuccessPage: app.SkipNativeAppSuccessPage,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@ func AppOIDCConfigToPb(app *query.OIDCApp) *app_pb.App_OidcConfig {
|
|||||||
ClockSkew: durationpb.New(app.ClockSkew),
|
ClockSkew: durationpb.New(app.ClockSkew),
|
||||||
AdditionalOrigins: app.AdditionalOrigins,
|
AdditionalOrigins: app.AdditionalOrigins,
|
||||||
AllowedOrigins: app.AllowedOrigins,
|
AllowedOrigins: app.AllowedOrigins,
|
||||||
|
SkipNativeAppSuccessPage: app.SkipNativeAppSuccessPage,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package login
|
package login
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
@ -44,26 +45,31 @@ func (l *Login) renderSuccessAndCallback(w http.ResponseWriter, r *http.Request,
|
|||||||
userData: l.getUserData(r, authReq, "LoginSuccess.Title", "", errID, errMessage),
|
userData: l.getUserData(r, authReq, "LoginSuccess.Title", "", errID, errMessage),
|
||||||
}
|
}
|
||||||
if authReq != nil {
|
if authReq != nil {
|
||||||
//the id will be set via the html (maybe change this with the login refactoring)
|
data.RedirectURI, err = l.authRequestCallback(r.Context(), authReq)
|
||||||
if _, ok := authReq.Request.(*domain.AuthRequestOIDC); ok {
|
if err != nil {
|
||||||
data.RedirectURI = l.oidcAuthCallbackURL(r.Context(), "")
|
l.renderInternalError(w, r, authReq, err)
|
||||||
} else if _, ok := authReq.Request.(*domain.AuthRequestSAML); ok {
|
return
|
||||||
data.RedirectURI = l.samlAuthCallbackURL(r.Context(), "")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
l.renderer.RenderTemplate(w, r, l.getTranslator(r.Context(), authReq), l.renderer.Templates[tmplLoginSuccess], data, nil)
|
l.renderer.RenderTemplate(w, r, l.getTranslator(r.Context(), authReq), l.renderer.Templates[tmplLoginSuccess], data, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Login) redirectToCallback(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest) {
|
func (l *Login) redirectToCallback(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest) {
|
||||||
var callback string
|
callback, err := l.authRequestCallback(r.Context(), authReq)
|
||||||
switch authReq.Request.(type) {
|
if err != nil {
|
||||||
case *domain.AuthRequestOIDC:
|
l.renderInternalError(w, r, authReq, err)
|
||||||
callback = l.oidcAuthCallbackURL(r.Context(), authReq.ID)
|
|
||||||
case *domain.AuthRequestSAML:
|
|
||||||
callback = l.samlAuthCallbackURL(r.Context(), authReq.ID)
|
|
||||||
default:
|
|
||||||
l.renderInternalError(w, r, authReq, caos_errs.ThrowInternal(nil, "LOGIN-rhjQF", "Errors.AuthRequest.RequestTypeNotSupported"))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
http.Redirect(w, r, callback, http.StatusFound)
|
http.Redirect(w, r, callback, http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *Login) authRequestCallback(ctx context.Context, authReq *domain.AuthRequest) (string, error) {
|
||||||
|
switch authReq.Request.(type) {
|
||||||
|
case *domain.AuthRequestOIDC:
|
||||||
|
return l.oidcAuthCallbackURL(ctx, authReq.ID), nil
|
||||||
|
case *domain.AuthRequestSAML:
|
||||||
|
return l.samlAuthCallbackURL(ctx, authReq.ID), nil
|
||||||
|
default:
|
||||||
|
return "", caos_errs.ThrowInternal(nil, "LOGIN-rhjQF", "Errors.AuthRequest.RequestTypeNotSupported")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,13 +5,6 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
function autoSubmit() {
|
function autoSubmit() {
|
||||||
let form = document.getElementsByTagName('form')[0];
|
let form = document.getElementsByTagName('form')[0];
|
||||||
if (form) {
|
if (form) {
|
||||||
let button = document.getElementById("redirect-button");
|
|
||||||
if (button) {
|
|
||||||
button.addEventListener("click", function (event) {
|
|
||||||
location.reload();
|
|
||||||
event.preventDefault();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
form.submit();
|
form.submit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1224,7 +1224,7 @@ func (repo *AuthRequestRepo) hasSucceededPage(ctx context.Context, request *doma
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
return app.OIDCConfig.AppType == domain.OIDCApplicationTypeNative, nil
|
return app.OIDCConfig.AppType == domain.OIDCApplicationTypeNative && !app.OIDCConfig.SkipNativeAppSuccessPage, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *AuthRequestRepo) getDomainPolicy(ctx context.Context, orgID string) (*query.DomainPolicy, error) {
|
func (repo *AuthRequestRepo) getDomainPolicy(ctx context.Context, orgID string) (*query.DomainPolicy, error) {
|
||||||
|
@ -161,7 +161,9 @@ func TestCommandSide_AddInstanceDomain(t *testing.T) {
|
|||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
time.Second*1,
|
time.Second*1,
|
||||||
[]string{"https://sub.test.ch"}),
|
[]string{"https://sub.test.ch"},
|
||||||
|
false,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
expectPush(
|
expectPush(
|
||||||
|
@ -33,6 +33,7 @@ type addOIDCApp struct {
|
|||||||
IDTokenUserinfoAssertion bool
|
IDTokenUserinfoAssertion bool
|
||||||
ClockSkew time.Duration
|
ClockSkew time.Duration
|
||||||
AdditionalOrigins []string
|
AdditionalOrigins []string
|
||||||
|
SkipSuccessPageForNativeApp bool
|
||||||
|
|
||||||
ClientID string
|
ClientID string
|
||||||
ClientSecret *crypto.CryptoValue
|
ClientSecret *crypto.CryptoValue
|
||||||
@ -109,6 +110,7 @@ func (c *Commands) AddOIDCAppCommand(app *addOIDCApp, clientSecretAlg crypto.Has
|
|||||||
app.IDTokenUserinfoAssertion,
|
app.IDTokenUserinfoAssertion,
|
||||||
app.ClockSkew,
|
app.ClockSkew,
|
||||||
app.AdditionalOrigins,
|
app.AdditionalOrigins,
|
||||||
|
app.SkipSuccessPageForNativeApp,
|
||||||
),
|
),
|
||||||
}, nil
|
}, nil
|
||||||
}, nil
|
}, nil
|
||||||
@ -191,7 +193,9 @@ func (c *Commands) addOIDCApplicationWithID(ctx context.Context, oidcApp *domain
|
|||||||
oidcApp.IDTokenRoleAssertion,
|
oidcApp.IDTokenRoleAssertion,
|
||||||
oidcApp.IDTokenUserinfoAssertion,
|
oidcApp.IDTokenUserinfoAssertion,
|
||||||
oidcApp.ClockSkew,
|
oidcApp.ClockSkew,
|
||||||
oidcApp.AdditionalOrigins))
|
oidcApp.AdditionalOrigins,
|
||||||
|
oidcApp.SkipNativeAppSuccessPage,
|
||||||
|
))
|
||||||
|
|
||||||
addedApplication.AppID = oidcApp.AppID
|
addedApplication.AppID = oidcApp.AppID
|
||||||
pushedEvents, err := c.eventstore.Push(ctx, events...)
|
pushedEvents, err := c.eventstore.Push(ctx, events...)
|
||||||
@ -241,7 +245,9 @@ func (c *Commands) ChangeOIDCApplication(ctx context.Context, oidc *domain.OIDCA
|
|||||||
oidc.IDTokenRoleAssertion,
|
oidc.IDTokenRoleAssertion,
|
||||||
oidc.IDTokenUserinfoAssertion,
|
oidc.IDTokenUserinfoAssertion,
|
||||||
oidc.ClockSkew,
|
oidc.ClockSkew,
|
||||||
oidc.AdditionalOrigins)
|
oidc.AdditionalOrigins,
|
||||||
|
oidc.SkipNativeAppSuccessPage,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ type OIDCApplicationWriteModel struct {
|
|||||||
ClockSkew time.Duration
|
ClockSkew time.Duration
|
||||||
State domain.AppState
|
State domain.AppState
|
||||||
AdditionalOrigins []string
|
AdditionalOrigins []string
|
||||||
|
SkipNativeAppSuccessPage bool
|
||||||
oidc bool
|
oidc bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,6 +157,7 @@ func (wm *OIDCApplicationWriteModel) appendAddOIDCEvent(e *project.OIDCConfigAdd
|
|||||||
wm.IDTokenUserinfoAssertion = e.IDTokenUserinfoAssertion
|
wm.IDTokenUserinfoAssertion = e.IDTokenUserinfoAssertion
|
||||||
wm.ClockSkew = e.ClockSkew
|
wm.ClockSkew = e.ClockSkew
|
||||||
wm.AdditionalOrigins = e.AdditionalOrigins
|
wm.AdditionalOrigins = e.AdditionalOrigins
|
||||||
|
wm.SkipNativeAppSuccessPage = e.SkipNativeAppSuccessPage
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wm *OIDCApplicationWriteModel) appendChangeOIDCEvent(e *project.OIDCConfigChangedEvent) {
|
func (wm *OIDCApplicationWriteModel) appendChangeOIDCEvent(e *project.OIDCConfigChangedEvent) {
|
||||||
@ -201,6 +203,9 @@ func (wm *OIDCApplicationWriteModel) appendChangeOIDCEvent(e *project.OIDCConfig
|
|||||||
if e.AdditionalOrigins != nil {
|
if e.AdditionalOrigins != nil {
|
||||||
wm.AdditionalOrigins = *e.AdditionalOrigins
|
wm.AdditionalOrigins = *e.AdditionalOrigins
|
||||||
}
|
}
|
||||||
|
if e.SkipNativeAppSuccessPage != nil {
|
||||||
|
wm.SkipNativeAppSuccessPage = *e.SkipNativeAppSuccessPage
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wm *OIDCApplicationWriteModel) Query() *eventstore.SearchQueryBuilder {
|
func (wm *OIDCApplicationWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||||
@ -240,6 +245,7 @@ func (wm *OIDCApplicationWriteModel) NewChangedEvent(
|
|||||||
idTokenUserinfoAssertion bool,
|
idTokenUserinfoAssertion bool,
|
||||||
clockSkew time.Duration,
|
clockSkew time.Duration,
|
||||||
additionalOrigins []string,
|
additionalOrigins []string,
|
||||||
|
skipNativeAppSuccessPage bool,
|
||||||
) (*project.OIDCConfigChangedEvent, bool, error) {
|
) (*project.OIDCConfigChangedEvent, bool, error) {
|
||||||
changes := make([]project.OIDCConfigChanges, 0)
|
changes := make([]project.OIDCConfigChanges, 0)
|
||||||
var err error
|
var err error
|
||||||
@ -286,6 +292,10 @@ func (wm *OIDCApplicationWriteModel) NewChangedEvent(
|
|||||||
if !reflect.DeepEqual(wm.AdditionalOrigins, additionalOrigins) {
|
if !reflect.DeepEqual(wm.AdditionalOrigins, additionalOrigins) {
|
||||||
changes = append(changes, project.ChangeAdditionalOrigins(additionalOrigins))
|
changes = append(changes, project.ChangeAdditionalOrigins(additionalOrigins))
|
||||||
}
|
}
|
||||||
|
if wm.SkipNativeAppSuccessPage != skipNativeAppSuccessPage {
|
||||||
|
changes = append(changes, project.ChangeSkipNativeAppSuccessPage(skipNativeAppSuccessPage))
|
||||||
|
}
|
||||||
|
|
||||||
if len(changes) == 0 {
|
if len(changes) == 0 {
|
||||||
return nil, false, nil
|
return nil, false, nil
|
||||||
}
|
}
|
||||||
|
@ -169,6 +169,7 @@ func TestAddOIDCApp(t *testing.T) {
|
|||||||
false,
|
false,
|
||||||
0,
|
0,
|
||||||
nil,
|
nil,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -325,7 +326,9 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
|
|||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
time.Second*1,
|
time.Second*1,
|
||||||
[]string{"https://sub.test.ch"}),
|
[]string{"https://sub.test.ch"},
|
||||||
|
true,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
uniqueConstraintsFromEventConstraint(project.NewAddApplicationUniqueConstraint("app", "project1")),
|
uniqueConstraintsFromEventConstraint(project.NewAddApplicationUniqueConstraint("app", "project1")),
|
||||||
@ -354,6 +357,7 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
|
|||||||
IDTokenUserinfoAssertion: true,
|
IDTokenUserinfoAssertion: true,
|
||||||
ClockSkew: time.Second * 1,
|
ClockSkew: time.Second * 1,
|
||||||
AdditionalOrigins: []string{"https://sub.test.ch"},
|
AdditionalOrigins: []string{"https://sub.test.ch"},
|
||||||
|
SkipNativeAppSuccessPage: true,
|
||||||
},
|
},
|
||||||
resourceOwner: "org1",
|
resourceOwner: "org1",
|
||||||
secretGenerator: GetMockSecretGenerator(t),
|
secretGenerator: GetMockSecretGenerator(t),
|
||||||
@ -382,6 +386,7 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
|
|||||||
IDTokenUserinfoAssertion: true,
|
IDTokenUserinfoAssertion: true,
|
||||||
ClockSkew: time.Second * 1,
|
ClockSkew: time.Second * 1,
|
||||||
AdditionalOrigins: []string{"https://sub.test.ch"},
|
AdditionalOrigins: []string{"https://sub.test.ch"},
|
||||||
|
SkipNativeAppSuccessPage: true,
|
||||||
State: domain.AppStateActive,
|
State: domain.AppStateActive,
|
||||||
Compliance: &domain.Compliance{},
|
Compliance: &domain.Compliance{},
|
||||||
},
|
},
|
||||||
@ -558,7 +563,9 @@ func TestCommandSide_ChangeOIDCApplication(t *testing.T) {
|
|||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
time.Second*1,
|
time.Second*1,
|
||||||
[]string{"https://sub.test.ch"}),
|
[]string{"https://sub.test.ch"},
|
||||||
|
true,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -585,6 +592,7 @@ func TestCommandSide_ChangeOIDCApplication(t *testing.T) {
|
|||||||
IDTokenUserinfoAssertion: true,
|
IDTokenUserinfoAssertion: true,
|
||||||
ClockSkew: time.Second * 1,
|
ClockSkew: time.Second * 1,
|
||||||
AdditionalOrigins: []string{"https://sub.test.ch"},
|
AdditionalOrigins: []string{"https://sub.test.ch"},
|
||||||
|
SkipNativeAppSuccessPage: true,
|
||||||
},
|
},
|
||||||
resourceOwner: "org1",
|
resourceOwner: "org1",
|
||||||
},
|
},
|
||||||
@ -629,7 +637,9 @@ func TestCommandSide_ChangeOIDCApplication(t *testing.T) {
|
|||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
time.Second*1,
|
time.Second*1,
|
||||||
[]string{"https://sub.test.ch"}),
|
[]string{"https://sub.test.ch"},
|
||||||
|
true,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
expectPush(
|
expectPush(
|
||||||
@ -666,6 +676,7 @@ func TestCommandSide_ChangeOIDCApplication(t *testing.T) {
|
|||||||
IDTokenUserinfoAssertion: false,
|
IDTokenUserinfoAssertion: false,
|
||||||
ClockSkew: time.Second * 2,
|
ClockSkew: time.Second * 2,
|
||||||
AdditionalOrigins: []string{"https://sub.test.ch"},
|
AdditionalOrigins: []string{"https://sub.test.ch"},
|
||||||
|
SkipNativeAppSuccessPage: true,
|
||||||
},
|
},
|
||||||
resourceOwner: "org1",
|
resourceOwner: "org1",
|
||||||
},
|
},
|
||||||
@ -692,6 +703,7 @@ func TestCommandSide_ChangeOIDCApplication(t *testing.T) {
|
|||||||
IDTokenUserinfoAssertion: false,
|
IDTokenUserinfoAssertion: false,
|
||||||
ClockSkew: time.Second * 2,
|
ClockSkew: time.Second * 2,
|
||||||
AdditionalOrigins: []string{"https://sub.test.ch"},
|
AdditionalOrigins: []string{"https://sub.test.ch"},
|
||||||
|
SkipNativeAppSuccessPage: true,
|
||||||
Compliance: &domain.Compliance{},
|
Compliance: &domain.Compliance{},
|
||||||
State: domain.AppStateActive,
|
State: domain.AppStateActive,
|
||||||
},
|
},
|
||||||
@ -826,7 +838,9 @@ func TestCommandSide_ChangeOIDCApplicationSecret(t *testing.T) {
|
|||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
time.Second*1,
|
time.Second*1,
|
||||||
[]string{"https://sub.test.ch"}),
|
[]string{"https://sub.test.ch"},
|
||||||
|
false,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
expectPush(
|
expectPush(
|
||||||
@ -877,6 +891,7 @@ func TestCommandSide_ChangeOIDCApplicationSecret(t *testing.T) {
|
|||||||
IDTokenUserinfoAssertion: true,
|
IDTokenUserinfoAssertion: true,
|
||||||
ClockSkew: time.Second * 1,
|
ClockSkew: time.Second * 1,
|
||||||
AdditionalOrigins: []string{"https://sub.test.ch"},
|
AdditionalOrigins: []string{"https://sub.test.ch"},
|
||||||
|
SkipNativeAppSuccessPage: false,
|
||||||
State: domain.AppStateActive,
|
State: domain.AppStateActive,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -25,14 +25,6 @@ func projectGrantWriteModelToProjectGrant(writeModel *ProjectGrantWriteModel) *d
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationWriteModelToApplication(writeModel *ApplicationWriteModel) domain.Application {
|
|
||||||
return &domain.ChangeApp{
|
|
||||||
AppID: writeModel.AppID,
|
|
||||||
AppName: writeModel.Name,
|
|
||||||
State: writeModel.State,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func oidcWriteModelToOIDCConfig(writeModel *OIDCApplicationWriteModel) *domain.OIDCApp {
|
func oidcWriteModelToOIDCConfig(writeModel *OIDCApplicationWriteModel) *domain.OIDCApp {
|
||||||
return &domain.OIDCApp{
|
return &domain.OIDCApp{
|
||||||
ObjectRoot: writeModelToObjectRoot(writeModel.WriteModel),
|
ObjectRoot: writeModelToObjectRoot(writeModel.WriteModel),
|
||||||
@ -54,6 +46,7 @@ func oidcWriteModelToOIDCConfig(writeModel *OIDCApplicationWriteModel) *domain.O
|
|||||||
IDTokenUserinfoAssertion: writeModel.IDTokenUserinfoAssertion,
|
IDTokenUserinfoAssertion: writeModel.IDTokenUserinfoAssertion,
|
||||||
ClockSkew: writeModel.ClockSkew,
|
ClockSkew: writeModel.ClockSkew,
|
||||||
AdditionalOrigins: writeModel.AdditionalOrigins,
|
AdditionalOrigins: writeModel.AdditionalOrigins,
|
||||||
|
SkipNativeAppSuccessPage: writeModel.SkipNativeAppSuccessPage,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,9 +3,9 @@ package command
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/crypto"
|
|
||||||
|
|
||||||
"github.com/zitadel/logging"
|
"github.com/zitadel/logging"
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/internal/crypto"
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
caos_errs "github.com/zitadel/zitadel/internal/errors"
|
caos_errs "github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||||
|
@ -45,6 +45,7 @@ type OIDCApp struct {
|
|||||||
IDTokenUserinfoAssertion bool
|
IDTokenUserinfoAssertion bool
|
||||||
ClockSkew time.Duration
|
ClockSkew time.Duration
|
||||||
AdditionalOrigins []string
|
AdditionalOrigins []string
|
||||||
|
SkipNativeAppSuccessPage bool
|
||||||
|
|
||||||
State AppState
|
State AppState
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,7 @@ type OIDCApp struct {
|
|||||||
ClockSkew time.Duration
|
ClockSkew time.Duration
|
||||||
AdditionalOrigins database.StringArray
|
AdditionalOrigins database.StringArray
|
||||||
AllowedOrigins database.StringArray
|
AllowedOrigins database.StringArray
|
||||||
|
SkipNativeAppSuccessPage bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type SAMLApp struct {
|
type SAMLApp struct {
|
||||||
@ -241,6 +242,10 @@ var (
|
|||||||
name: projection.AppOIDCConfigColumnAdditionalOrigins,
|
name: projection.AppOIDCConfigColumnAdditionalOrigins,
|
||||||
table: appOIDCConfigsTable,
|
table: appOIDCConfigsTable,
|
||||||
}
|
}
|
||||||
|
AppOIDCConfigColumnSkipNativeAppSuccessPage = Column{
|
||||||
|
name: projection.AppOIDCConfigColumnSkipNativeAppSuccessPage,
|
||||||
|
table: appOIDCConfigsTable,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (q *Queries) AppByProjectAndAppID(ctx context.Context, shouldTriggerBulk bool, projectID, appID string, withOwnerRemoved bool) (_ *App, err error) {
|
func (q *Queries) AppByProjectAndAppID(ctx context.Context, shouldTriggerBulk bool, projectID, appID string, withOwnerRemoved bool) (_ *App, err error) {
|
||||||
@ -535,6 +540,7 @@ func prepareAppQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder,
|
|||||||
AppOIDCConfigColumnIDTokenUserinfoAssertion.identifier(),
|
AppOIDCConfigColumnIDTokenUserinfoAssertion.identifier(),
|
||||||
AppOIDCConfigColumnClockSkew.identifier(),
|
AppOIDCConfigColumnClockSkew.identifier(),
|
||||||
AppOIDCConfigColumnAdditionalOrigins.identifier(),
|
AppOIDCConfigColumnAdditionalOrigins.identifier(),
|
||||||
|
AppOIDCConfigColumnSkipNativeAppSuccessPage.identifier(),
|
||||||
|
|
||||||
AppSAMLConfigColumnAppID.identifier(),
|
AppSAMLConfigColumnAppID.identifier(),
|
||||||
AppSAMLConfigColumnEntityID.identifier(),
|
AppSAMLConfigColumnEntityID.identifier(),
|
||||||
@ -583,6 +589,7 @@ func prepareAppQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder,
|
|||||||
&oidcConfig.iDTokenUserinfoAssertion,
|
&oidcConfig.iDTokenUserinfoAssertion,
|
||||||
&oidcConfig.clockSkew,
|
&oidcConfig.clockSkew,
|
||||||
&oidcConfig.additionalOrigins,
|
&oidcConfig.additionalOrigins,
|
||||||
|
&oidcConfig.skipNativeAppSuccessPage,
|
||||||
|
|
||||||
&samlConfig.appID,
|
&samlConfig.appID,
|
||||||
&samlConfig.entityID,
|
&samlConfig.entityID,
|
||||||
@ -703,6 +710,7 @@ func prepareAppsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder
|
|||||||
AppOIDCConfigColumnIDTokenUserinfoAssertion.identifier(),
|
AppOIDCConfigColumnIDTokenUserinfoAssertion.identifier(),
|
||||||
AppOIDCConfigColumnClockSkew.identifier(),
|
AppOIDCConfigColumnClockSkew.identifier(),
|
||||||
AppOIDCConfigColumnAdditionalOrigins.identifier(),
|
AppOIDCConfigColumnAdditionalOrigins.identifier(),
|
||||||
|
AppOIDCConfigColumnSkipNativeAppSuccessPage.identifier(),
|
||||||
|
|
||||||
AppSAMLConfigColumnAppID.identifier(),
|
AppSAMLConfigColumnAppID.identifier(),
|
||||||
AppSAMLConfigColumnEntityID.identifier(),
|
AppSAMLConfigColumnEntityID.identifier(),
|
||||||
@ -754,6 +762,7 @@ func prepareAppsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder
|
|||||||
&oidcConfig.iDTokenUserinfoAssertion,
|
&oidcConfig.iDTokenUserinfoAssertion,
|
||||||
&oidcConfig.clockSkew,
|
&oidcConfig.clockSkew,
|
||||||
&oidcConfig.additionalOrigins,
|
&oidcConfig.additionalOrigins,
|
||||||
|
&oidcConfig.skipNativeAppSuccessPage,
|
||||||
|
|
||||||
&samlConfig.appID,
|
&samlConfig.appID,
|
||||||
&samlConfig.entityID,
|
&samlConfig.entityID,
|
||||||
@ -825,6 +834,7 @@ type sqlOIDCConfig struct {
|
|||||||
additionalOrigins database.StringArray
|
additionalOrigins database.StringArray
|
||||||
responseTypes database.EnumArray[domain.OIDCResponseType]
|
responseTypes database.EnumArray[domain.OIDCResponseType]
|
||||||
grantTypes database.EnumArray[domain.OIDCGrantType]
|
grantTypes database.EnumArray[domain.OIDCGrantType]
|
||||||
|
skipNativeAppSuccessPage sql.NullBool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c sqlOIDCConfig) set(app *App) {
|
func (c sqlOIDCConfig) set(app *App) {
|
||||||
@ -847,6 +857,7 @@ func (c sqlOIDCConfig) set(app *App) {
|
|||||||
AdditionalOrigins: c.additionalOrigins,
|
AdditionalOrigins: c.additionalOrigins,
|
||||||
ResponseTypes: c.responseTypes,
|
ResponseTypes: c.responseTypes,
|
||||||
GrantTypes: c.grantTypes,
|
GrantTypes: c.grantTypes,
|
||||||
|
SkipNativeAppSuccessPage: c.skipNativeAppSuccessPage.Bool,
|
||||||
}
|
}
|
||||||
compliance := domain.GetOIDCCompliance(app.OIDCConfig.Version, app.OIDCConfig.AppType, app.OIDCConfig.GrantTypes, app.OIDCConfig.ResponseTypes, app.OIDCConfig.AuthMethodType, app.OIDCConfig.RedirectURIs)
|
compliance := domain.GetOIDCCompliance(app.OIDCConfig.Version, app.OIDCConfig.AppType, app.OIDCConfig.GrantTypes, app.OIDCConfig.ResponseTypes, app.OIDCConfig.AuthMethodType, app.OIDCConfig.RedirectURIs)
|
||||||
app.OIDCConfig.ComplianceProblems = compliance.Problems
|
app.OIDCConfig.ComplianceProblems = compliance.Problems
|
||||||
|
@ -15,96 +15,98 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
expectedAppQuery = regexp.QuoteMeta(`SELECT projections.apps4.id,` +
|
expectedAppQuery = regexp.QuoteMeta(`SELECT projections.apps5.id,` +
|
||||||
` projections.apps4.name,` +
|
` projections.apps5.name,` +
|
||||||
` projections.apps4.project_id,` +
|
` projections.apps5.project_id,` +
|
||||||
` projections.apps4.creation_date,` +
|
` projections.apps5.creation_date,` +
|
||||||
` projections.apps4.change_date,` +
|
` projections.apps5.change_date,` +
|
||||||
` projections.apps4.resource_owner,` +
|
` projections.apps5.resource_owner,` +
|
||||||
` projections.apps4.state,` +
|
` projections.apps5.state,` +
|
||||||
` projections.apps4.sequence,` +
|
` projections.apps5.sequence,` +
|
||||||
// api config
|
// api config
|
||||||
` projections.apps4_api_configs.app_id,` +
|
` projections.apps5_api_configs.app_id,` +
|
||||||
` projections.apps4_api_configs.client_id,` +
|
` projections.apps5_api_configs.client_id,` +
|
||||||
` projections.apps4_api_configs.auth_method,` +
|
` projections.apps5_api_configs.auth_method,` +
|
||||||
// oidc config
|
// oidc config
|
||||||
` projections.apps4_oidc_configs.app_id,` +
|
` projections.apps5_oidc_configs.app_id,` +
|
||||||
` projections.apps4_oidc_configs.version,` +
|
` projections.apps5_oidc_configs.version,` +
|
||||||
` projections.apps4_oidc_configs.client_id,` +
|
` projections.apps5_oidc_configs.client_id,` +
|
||||||
` projections.apps4_oidc_configs.redirect_uris,` +
|
` projections.apps5_oidc_configs.redirect_uris,` +
|
||||||
` projections.apps4_oidc_configs.response_types,` +
|
` projections.apps5_oidc_configs.response_types,` +
|
||||||
` projections.apps4_oidc_configs.grant_types,` +
|
` projections.apps5_oidc_configs.grant_types,` +
|
||||||
` projections.apps4_oidc_configs.application_type,` +
|
` projections.apps5_oidc_configs.application_type,` +
|
||||||
` projections.apps4_oidc_configs.auth_method_type,` +
|
` projections.apps5_oidc_configs.auth_method_type,` +
|
||||||
` projections.apps4_oidc_configs.post_logout_redirect_uris,` +
|
` projections.apps5_oidc_configs.post_logout_redirect_uris,` +
|
||||||
` projections.apps4_oidc_configs.is_dev_mode,` +
|
` projections.apps5_oidc_configs.is_dev_mode,` +
|
||||||
` projections.apps4_oidc_configs.access_token_type,` +
|
` projections.apps5_oidc_configs.access_token_type,` +
|
||||||
` projections.apps4_oidc_configs.access_token_role_assertion,` +
|
` projections.apps5_oidc_configs.access_token_role_assertion,` +
|
||||||
` projections.apps4_oidc_configs.id_token_role_assertion,` +
|
` projections.apps5_oidc_configs.id_token_role_assertion,` +
|
||||||
` projections.apps4_oidc_configs.id_token_userinfo_assertion,` +
|
` projections.apps5_oidc_configs.id_token_userinfo_assertion,` +
|
||||||
` projections.apps4_oidc_configs.clock_skew,` +
|
` projections.apps5_oidc_configs.clock_skew,` +
|
||||||
` projections.apps4_oidc_configs.additional_origins,` +
|
` projections.apps5_oidc_configs.additional_origins,` +
|
||||||
|
` projections.apps5_oidc_configs.skip_native_app_success_page,` +
|
||||||
//saml config
|
//saml config
|
||||||
` projections.apps4_saml_configs.app_id,` +
|
` projections.apps5_saml_configs.app_id,` +
|
||||||
` projections.apps4_saml_configs.entity_id,` +
|
` projections.apps5_saml_configs.entity_id,` +
|
||||||
` projections.apps4_saml_configs.metadata,` +
|
` projections.apps5_saml_configs.metadata,` +
|
||||||
` projections.apps4_saml_configs.metadata_url` +
|
` projections.apps5_saml_configs.metadata_url` +
|
||||||
` FROM projections.apps4` +
|
` FROM projections.apps5` +
|
||||||
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
|
` LEFT JOIN projections.apps5_api_configs ON projections.apps5.id = projections.apps5_api_configs.app_id AND projections.apps5.instance_id = projections.apps5_api_configs.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
|
` LEFT JOIN projections.apps5_oidc_configs ON projections.apps5.id = projections.apps5_oidc_configs.app_id AND projections.apps5.instance_id = projections.apps5_oidc_configs.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id` +
|
` LEFT JOIN projections.apps5_saml_configs ON projections.apps5.id = projections.apps5_saml_configs.app_id AND projections.apps5.instance_id = projections.apps5_saml_configs.instance_id` +
|
||||||
` AS OF SYSTEM TIME '-1 ms'`)
|
` AS OF SYSTEM TIME '-1 ms'`)
|
||||||
expectedAppsQuery = regexp.QuoteMeta(`SELECT projections.apps4.id,` +
|
expectedAppsQuery = regexp.QuoteMeta(`SELECT projections.apps5.id,` +
|
||||||
` projections.apps4.name,` +
|
` projections.apps5.name,` +
|
||||||
` projections.apps4.project_id,` +
|
` projections.apps5.project_id,` +
|
||||||
` projections.apps4.creation_date,` +
|
` projections.apps5.creation_date,` +
|
||||||
` projections.apps4.change_date,` +
|
` projections.apps5.change_date,` +
|
||||||
` projections.apps4.resource_owner,` +
|
` projections.apps5.resource_owner,` +
|
||||||
` projections.apps4.state,` +
|
` projections.apps5.state,` +
|
||||||
` projections.apps4.sequence,` +
|
` projections.apps5.sequence,` +
|
||||||
// api config
|
// api config
|
||||||
` projections.apps4_api_configs.app_id,` +
|
` projections.apps5_api_configs.app_id,` +
|
||||||
` projections.apps4_api_configs.client_id,` +
|
` projections.apps5_api_configs.client_id,` +
|
||||||
` projections.apps4_api_configs.auth_method,` +
|
` projections.apps5_api_configs.auth_method,` +
|
||||||
// oidc config
|
// oidc config
|
||||||
` projections.apps4_oidc_configs.app_id,` +
|
` projections.apps5_oidc_configs.app_id,` +
|
||||||
` projections.apps4_oidc_configs.version,` +
|
` projections.apps5_oidc_configs.version,` +
|
||||||
` projections.apps4_oidc_configs.client_id,` +
|
` projections.apps5_oidc_configs.client_id,` +
|
||||||
` projections.apps4_oidc_configs.redirect_uris,` +
|
` projections.apps5_oidc_configs.redirect_uris,` +
|
||||||
` projections.apps4_oidc_configs.response_types,` +
|
` projections.apps5_oidc_configs.response_types,` +
|
||||||
` projections.apps4_oidc_configs.grant_types,` +
|
` projections.apps5_oidc_configs.grant_types,` +
|
||||||
` projections.apps4_oidc_configs.application_type,` +
|
` projections.apps5_oidc_configs.application_type,` +
|
||||||
` projections.apps4_oidc_configs.auth_method_type,` +
|
` projections.apps5_oidc_configs.auth_method_type,` +
|
||||||
` projections.apps4_oidc_configs.post_logout_redirect_uris,` +
|
` projections.apps5_oidc_configs.post_logout_redirect_uris,` +
|
||||||
` projections.apps4_oidc_configs.is_dev_mode,` +
|
` projections.apps5_oidc_configs.is_dev_mode,` +
|
||||||
` projections.apps4_oidc_configs.access_token_type,` +
|
` projections.apps5_oidc_configs.access_token_type,` +
|
||||||
` projections.apps4_oidc_configs.access_token_role_assertion,` +
|
` projections.apps5_oidc_configs.access_token_role_assertion,` +
|
||||||
` projections.apps4_oidc_configs.id_token_role_assertion,` +
|
` projections.apps5_oidc_configs.id_token_role_assertion,` +
|
||||||
` projections.apps4_oidc_configs.id_token_userinfo_assertion,` +
|
` projections.apps5_oidc_configs.id_token_userinfo_assertion,` +
|
||||||
` projections.apps4_oidc_configs.clock_skew,` +
|
` projections.apps5_oidc_configs.clock_skew,` +
|
||||||
` projections.apps4_oidc_configs.additional_origins,` +
|
` projections.apps5_oidc_configs.additional_origins,` +
|
||||||
|
` projections.apps5_oidc_configs.skip_native_app_success_page,` +
|
||||||
//saml config
|
//saml config
|
||||||
` projections.apps4_saml_configs.app_id,` +
|
` projections.apps5_saml_configs.app_id,` +
|
||||||
` projections.apps4_saml_configs.entity_id,` +
|
` projections.apps5_saml_configs.entity_id,` +
|
||||||
` projections.apps4_saml_configs.metadata,` +
|
` projections.apps5_saml_configs.metadata,` +
|
||||||
` projections.apps4_saml_configs.metadata_url,` +
|
` projections.apps5_saml_configs.metadata_url,` +
|
||||||
` COUNT(*) OVER ()` +
|
` COUNT(*) OVER ()` +
|
||||||
` FROM projections.apps4` +
|
` FROM projections.apps5` +
|
||||||
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
|
` LEFT JOIN projections.apps5_api_configs ON projections.apps5.id = projections.apps5_api_configs.app_id AND projections.apps5.instance_id = projections.apps5_api_configs.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
|
` LEFT JOIN projections.apps5_oidc_configs ON projections.apps5.id = projections.apps5_oidc_configs.app_id AND projections.apps5.instance_id = projections.apps5_oidc_configs.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id` +
|
` LEFT JOIN projections.apps5_saml_configs ON projections.apps5.id = projections.apps5_saml_configs.app_id AND projections.apps5.instance_id = projections.apps5_saml_configs.instance_id` +
|
||||||
` AS OF SYSTEM TIME '-1 ms'`)
|
` AS OF SYSTEM TIME '-1 ms'`)
|
||||||
expectedAppIDsQuery = regexp.QuoteMeta(`SELECT projections.apps4_api_configs.client_id,` +
|
expectedAppIDsQuery = regexp.QuoteMeta(`SELECT projections.apps5_api_configs.client_id,` +
|
||||||
` projections.apps4_oidc_configs.client_id` +
|
` projections.apps5_oidc_configs.client_id` +
|
||||||
` FROM projections.apps4` +
|
` FROM projections.apps5` +
|
||||||
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
|
` LEFT JOIN projections.apps5_api_configs ON projections.apps5.id = projections.apps5_api_configs.app_id AND projections.apps5.instance_id = projections.apps5_api_configs.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
|
` LEFT JOIN projections.apps5_oidc_configs ON projections.apps5.id = projections.apps5_oidc_configs.app_id AND projections.apps5.instance_id = projections.apps5_oidc_configs.instance_id` +
|
||||||
` AS OF SYSTEM TIME '-1 ms'`)
|
` AS OF SYSTEM TIME '-1 ms'`)
|
||||||
expectedProjectIDByAppQuery = regexp.QuoteMeta(`SELECT projections.apps4.project_id` +
|
expectedProjectIDByAppQuery = regexp.QuoteMeta(`SELECT projections.apps5.project_id` +
|
||||||
` FROM projections.apps4` +
|
` FROM projections.apps5` +
|
||||||
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
|
` LEFT JOIN projections.apps5_api_configs ON projections.apps5.id = projections.apps5_api_configs.app_id AND projections.apps5.instance_id = projections.apps5_api_configs.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
|
` LEFT JOIN projections.apps5_oidc_configs ON projections.apps5.id = projections.apps5_oidc_configs.app_id AND projections.apps5.instance_id = projections.apps5_oidc_configs.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id` +
|
` LEFT JOIN projections.apps5_saml_configs ON projections.apps5.id = projections.apps5_saml_configs.app_id AND projections.apps5.instance_id = projections.apps5_saml_configs.instance_id` +
|
||||||
` AS OF SYSTEM TIME '-1 ms'`)
|
` AS OF SYSTEM TIME '-1 ms'`)
|
||||||
expectedProjectByAppQuery = regexp.QuoteMeta(`SELECT projections.projects3.id,` +
|
expectedProjectByAppQuery = regexp.QuoteMeta(`SELECT projections.projects3.id,` +
|
||||||
` projections.projects3.creation_date,` +
|
` projections.projects3.creation_date,` +
|
||||||
@ -118,10 +120,10 @@ var (
|
|||||||
` projections.projects3.has_project_check,` +
|
` projections.projects3.has_project_check,` +
|
||||||
` projections.projects3.private_labeling_setting` +
|
` projections.projects3.private_labeling_setting` +
|
||||||
` FROM projections.projects3` +
|
` FROM projections.projects3` +
|
||||||
` JOIN projections.apps4 ON projections.projects3.id = projections.apps4.project_id AND projections.projects3.instance_id = projections.apps4.instance_id` +
|
` JOIN projections.apps5 ON projections.projects3.id = projections.apps5.project_id AND projections.projects3.instance_id = projections.apps5.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
|
` LEFT JOIN projections.apps5_api_configs ON projections.apps5.id = projections.apps5_api_configs.app_id AND projections.apps5.instance_id = projections.apps5_api_configs.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
|
` LEFT JOIN projections.apps5_oidc_configs ON projections.apps5.id = projections.apps5_oidc_configs.app_id AND projections.apps5.instance_id = projections.apps5_oidc_configs.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id` +
|
` LEFT JOIN projections.apps5_saml_configs ON projections.apps5.id = projections.apps5_saml_configs.app_id AND projections.apps5.instance_id = projections.apps5_saml_configs.instance_id` +
|
||||||
` AS OF SYSTEM TIME '-1 ms'`)
|
` AS OF SYSTEM TIME '-1 ms'`)
|
||||||
|
|
||||||
appCols = database.StringArray{
|
appCols = database.StringArray{
|
||||||
@ -154,6 +156,7 @@ var (
|
|||||||
"id_token_userinfo_assertion",
|
"id_token_userinfo_assertion",
|
||||||
"clock_skew",
|
"clock_skew",
|
||||||
"additional_origins",
|
"additional_origins",
|
||||||
|
"skip_native_app_success_page",
|
||||||
//saml config
|
//saml config
|
||||||
"app_id",
|
"app_id",
|
||||||
"entity_id",
|
"entity_id",
|
||||||
@ -224,6 +227,7 @@ func Test_AppsPrepare(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
nil,
|
||||||
// saml config
|
// saml config
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -289,6 +293,7 @@ func Test_AppsPrepare(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
nil,
|
||||||
// saml config
|
// saml config
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -357,6 +362,7 @@ func Test_AppsPrepare(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
nil,
|
||||||
// saml config
|
// saml config
|
||||||
"app-id",
|
"app-id",
|
||||||
"https://test.com/saml/metadata",
|
"https://test.com/saml/metadata",
|
||||||
@ -427,6 +433,7 @@ func Test_AppsPrepare(t *testing.T) {
|
|||||||
true,
|
true,
|
||||||
1 * time.Second,
|
1 * time.Second,
|
||||||
database.StringArray{"additional.origin"},
|
database.StringArray{"additional.origin"},
|
||||||
|
false,
|
||||||
// saml config
|
// saml config
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -468,6 +475,7 @@ func Test_AppsPrepare(t *testing.T) {
|
|||||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||||
ComplianceProblems: nil,
|
ComplianceProblems: nil,
|
||||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||||
|
SkipNativeAppSuccessPage: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -511,6 +519,7 @@ func Test_AppsPrepare(t *testing.T) {
|
|||||||
true,
|
true,
|
||||||
1 * time.Second,
|
1 * time.Second,
|
||||||
database.StringArray{"additional.origin"},
|
database.StringArray{"additional.origin"},
|
||||||
|
false,
|
||||||
// saml config
|
// saml config
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -552,6 +561,7 @@ func Test_AppsPrepare(t *testing.T) {
|
|||||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||||
ComplianceProblems: nil,
|
ComplianceProblems: nil,
|
||||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||||
|
SkipNativeAppSuccessPage: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -595,6 +605,7 @@ func Test_AppsPrepare(t *testing.T) {
|
|||||||
true,
|
true,
|
||||||
1 * time.Second,
|
1 * time.Second,
|
||||||
database.StringArray{"additional.origin"},
|
database.StringArray{"additional.origin"},
|
||||||
|
false,
|
||||||
// saml config
|
// saml config
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -636,6 +647,7 @@ func Test_AppsPrepare(t *testing.T) {
|
|||||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||||
ComplianceProblems: nil,
|
ComplianceProblems: nil,
|
||||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||||
|
SkipNativeAppSuccessPage: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -679,6 +691,7 @@ func Test_AppsPrepare(t *testing.T) {
|
|||||||
true,
|
true,
|
||||||
1 * time.Second,
|
1 * time.Second,
|
||||||
database.StringArray{"additional.origin"},
|
database.StringArray{"additional.origin"},
|
||||||
|
false,
|
||||||
// saml config
|
// saml config
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -720,6 +733,7 @@ func Test_AppsPrepare(t *testing.T) {
|
|||||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||||
ComplianceProblems: nil,
|
ComplianceProblems: nil,
|
||||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||||
|
SkipNativeAppSuccessPage: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -763,6 +777,7 @@ func Test_AppsPrepare(t *testing.T) {
|
|||||||
true,
|
true,
|
||||||
1 * time.Second,
|
1 * time.Second,
|
||||||
database.StringArray{"additional.origin"},
|
database.StringArray{"additional.origin"},
|
||||||
|
false,
|
||||||
// saml config
|
// saml config
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -804,6 +819,93 @@ func Test_AppsPrepare(t *testing.T) {
|
|||||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||||
ComplianceProblems: nil,
|
ComplianceProblems: nil,
|
||||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||||
|
SkipNativeAppSuccessPage: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prepareAppsQuery oidc app native success page skip",
|
||||||
|
prepare: prepareAppsQuery,
|
||||||
|
want: want{
|
||||||
|
sqlExpectations: mockQueries(
|
||||||
|
expectedAppsQuery,
|
||||||
|
appsCols,
|
||||||
|
[][]driver.Value{
|
||||||
|
{
|
||||||
|
"app-id",
|
||||||
|
"app-name",
|
||||||
|
"project-id",
|
||||||
|
testNow,
|
||||||
|
testNow,
|
||||||
|
"ro",
|
||||||
|
domain.AppStateActive,
|
||||||
|
uint64(20211109),
|
||||||
|
// api config
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
// oidc config
|
||||||
|
"app-id",
|
||||||
|
domain.OIDCVersionV1,
|
||||||
|
"oidc-client-id",
|
||||||
|
database.StringArray{"https://redirect.to/me"},
|
||||||
|
database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken},
|
||||||
|
database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit},
|
||||||
|
domain.OIDCApplicationTypeNative,
|
||||||
|
domain.OIDCAuthMethodTypeNone,
|
||||||
|
database.StringArray{"post.logout.ch"},
|
||||||
|
false,
|
||||||
|
domain.OIDCTokenTypeJWT,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
1 * time.Second,
|
||||||
|
database.StringArray{"additional.origin"},
|
||||||
|
true,
|
||||||
|
// saml config
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
object: &Apps{
|
||||||
|
SearchResponse: SearchResponse{
|
||||||
|
Count: 1,
|
||||||
|
},
|
||||||
|
Apps: []*App{
|
||||||
|
{
|
||||||
|
ID: "app-id",
|
||||||
|
CreationDate: testNow,
|
||||||
|
ChangeDate: testNow,
|
||||||
|
ResourceOwner: "ro",
|
||||||
|
State: domain.AppStateActive,
|
||||||
|
Sequence: 20211109,
|
||||||
|
Name: "app-name",
|
||||||
|
ProjectID: "project-id",
|
||||||
|
OIDCConfig: &OIDCApp{
|
||||||
|
Version: domain.OIDCVersionV1,
|
||||||
|
ClientID: "oidc-client-id",
|
||||||
|
RedirectURIs: database.StringArray{"https://redirect.to/me"},
|
||||||
|
ResponseTypes: database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken},
|
||||||
|
GrantTypes: database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit},
|
||||||
|
AppType: domain.OIDCApplicationTypeNative,
|
||||||
|
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||||
|
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||||
|
IsDevMode: false,
|
||||||
|
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||||
|
AssertAccessTokenRole: false,
|
||||||
|
AssertIDTokenRole: false,
|
||||||
|
AssertIDTokenUserinfo: true,
|
||||||
|
ClockSkew: 1 * time.Second,
|
||||||
|
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||||
|
ComplianceProblems: nil,
|
||||||
|
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||||
|
SkipNativeAppSuccessPage: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -847,6 +949,7 @@ func Test_AppsPrepare(t *testing.T) {
|
|||||||
true,
|
true,
|
||||||
1 * time.Second,
|
1 * time.Second,
|
||||||
database.StringArray{"additional.origin"},
|
database.StringArray{"additional.origin"},
|
||||||
|
false,
|
||||||
// saml config
|
// saml config
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -883,6 +986,7 @@ func Test_AppsPrepare(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
nil,
|
||||||
// saml config
|
// saml config
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -919,6 +1023,7 @@ func Test_AppsPrepare(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
nil,
|
||||||
// saml config
|
// saml config
|
||||||
"saml-app-id",
|
"saml-app-id",
|
||||||
"https://test.com/saml/metadata",
|
"https://test.com/saml/metadata",
|
||||||
@ -960,6 +1065,7 @@ func Test_AppsPrepare(t *testing.T) {
|
|||||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||||
ComplianceProblems: nil,
|
ComplianceProblems: nil,
|
||||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||||
|
SkipNativeAppSuccessPage: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1085,6 +1191,7 @@ func Test_AppPrepare(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
nil,
|
||||||
// saml config
|
// saml config
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -1142,6 +1249,7 @@ func Test_AppPrepare(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
nil,
|
||||||
// saml config
|
// saml config
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -1204,6 +1312,7 @@ func Test_AppPrepare(t *testing.T) {
|
|||||||
true,
|
true,
|
||||||
1 * time.Second,
|
1 * time.Second,
|
||||||
database.StringArray{"additional.origin"},
|
database.StringArray{"additional.origin"},
|
||||||
|
false,
|
||||||
// saml config
|
// saml config
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -1240,6 +1349,7 @@ func Test_AppPrepare(t *testing.T) {
|
|||||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||||
ComplianceProblems: nil,
|
ComplianceProblems: nil,
|
||||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||||
|
SkipNativeAppSuccessPage: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
@ -1280,6 +1390,7 @@ func Test_AppPrepare(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
nil,
|
||||||
// saml config
|
// saml config
|
||||||
"app-id",
|
"app-id",
|
||||||
"https://test.com/saml/metadata",
|
"https://test.com/saml/metadata",
|
||||||
@ -1343,6 +1454,7 @@ func Test_AppPrepare(t *testing.T) {
|
|||||||
true,
|
true,
|
||||||
1 * time.Second,
|
1 * time.Second,
|
||||||
database.StringArray{"additional.origin"},
|
database.StringArray{"additional.origin"},
|
||||||
|
false,
|
||||||
// saml config
|
// saml config
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -1379,6 +1491,7 @@ func Test_AppPrepare(t *testing.T) {
|
|||||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||||
ComplianceProblems: nil,
|
ComplianceProblems: nil,
|
||||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||||
|
SkipNativeAppSuccessPage: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1420,6 +1533,7 @@ func Test_AppPrepare(t *testing.T) {
|
|||||||
true,
|
true,
|
||||||
1 * time.Second,
|
1 * time.Second,
|
||||||
database.StringArray{"additional.origin"},
|
database.StringArray{"additional.origin"},
|
||||||
|
false,
|
||||||
// saml config
|
// saml config
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -1456,6 +1570,7 @@ func Test_AppPrepare(t *testing.T) {
|
|||||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||||
ComplianceProblems: nil,
|
ComplianceProblems: nil,
|
||||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||||
|
SkipNativeAppSuccessPage: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1497,6 +1612,7 @@ func Test_AppPrepare(t *testing.T) {
|
|||||||
true,
|
true,
|
||||||
1 * time.Second,
|
1 * time.Second,
|
||||||
database.StringArray{"additional.origin"},
|
database.StringArray{"additional.origin"},
|
||||||
|
false,
|
||||||
// saml config
|
// saml config
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -1533,6 +1649,7 @@ func Test_AppPrepare(t *testing.T) {
|
|||||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||||
ComplianceProblems: nil,
|
ComplianceProblems: nil,
|
||||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||||
|
SkipNativeAppSuccessPage: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1574,6 +1691,7 @@ func Test_AppPrepare(t *testing.T) {
|
|||||||
false,
|
false,
|
||||||
1 * time.Second,
|
1 * time.Second,
|
||||||
database.StringArray{"additional.origin"},
|
database.StringArray{"additional.origin"},
|
||||||
|
false,
|
||||||
// saml config
|
// saml config
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -1610,6 +1728,7 @@ func Test_AppPrepare(t *testing.T) {
|
|||||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||||
ComplianceProblems: nil,
|
ComplianceProblems: nil,
|
||||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||||
|
SkipNativeAppSuccessPage: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -15,7 +15,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
AppProjectionTable = "projections.apps4"
|
AppProjectionTable = "projections.apps5"
|
||||||
AppAPITable = AppProjectionTable + "_" + appAPITableSuffix
|
AppAPITable = AppProjectionTable + "_" + appAPITableSuffix
|
||||||
AppOIDCTable = AppProjectionTable + "_" + appOIDCTableSuffix
|
AppOIDCTable = AppProjectionTable + "_" + appOIDCTableSuffix
|
||||||
AppSAMLTable = AppProjectionTable + "_" + appSAMLTableSuffix
|
AppSAMLTable = AppProjectionTable + "_" + appSAMLTableSuffix
|
||||||
@ -57,6 +57,7 @@ const (
|
|||||||
AppOIDCConfigColumnIDTokenUserinfoAssertion = "id_token_userinfo_assertion"
|
AppOIDCConfigColumnIDTokenUserinfoAssertion = "id_token_userinfo_assertion"
|
||||||
AppOIDCConfigColumnClockSkew = "clock_skew"
|
AppOIDCConfigColumnClockSkew = "clock_skew"
|
||||||
AppOIDCConfigColumnAdditionalOrigins = "additional_origins"
|
AppOIDCConfigColumnAdditionalOrigins = "additional_origins"
|
||||||
|
AppOIDCConfigColumnSkipNativeAppSuccessPage = "skip_native_app_success_page"
|
||||||
|
|
||||||
appSAMLTableSuffix = "saml_configs"
|
appSAMLTableSuffix = "saml_configs"
|
||||||
AppSAMLConfigColumnAppID = "app_id"
|
AppSAMLConfigColumnAppID = "app_id"
|
||||||
@ -122,6 +123,7 @@ func newAppProjection(ctx context.Context, config crdb.StatementHandlerConfig) *
|
|||||||
crdb.NewColumn(AppOIDCConfigColumnIDTokenUserinfoAssertion, crdb.ColumnTypeBool, crdb.Default(false)),
|
crdb.NewColumn(AppOIDCConfigColumnIDTokenUserinfoAssertion, crdb.ColumnTypeBool, crdb.Default(false)),
|
||||||
crdb.NewColumn(AppOIDCConfigColumnClockSkew, crdb.ColumnTypeInt64, crdb.Default(0)),
|
crdb.NewColumn(AppOIDCConfigColumnClockSkew, crdb.ColumnTypeInt64, crdb.Default(0)),
|
||||||
crdb.NewColumn(AppOIDCConfigColumnAdditionalOrigins, crdb.ColumnTypeTextArray, crdb.Nullable()),
|
crdb.NewColumn(AppOIDCConfigColumnAdditionalOrigins, crdb.ColumnTypeTextArray, crdb.Nullable()),
|
||||||
|
crdb.NewColumn(AppOIDCConfigColumnSkipNativeAppSuccessPage, crdb.ColumnTypeBool, crdb.Default(false)),
|
||||||
},
|
},
|
||||||
crdb.NewPrimaryKey(AppOIDCConfigColumnInstanceID, AppOIDCConfigColumnAppID),
|
crdb.NewPrimaryKey(AppOIDCConfigColumnInstanceID, AppOIDCConfigColumnAppID),
|
||||||
appOIDCTableSuffix,
|
appOIDCTableSuffix,
|
||||||
@ -463,6 +465,7 @@ func (p *appProjection) reduceOIDCConfigAdded(event eventstore.Event) (*handler.
|
|||||||
handler.NewCol(AppOIDCConfigColumnIDTokenUserinfoAssertion, e.IDTokenUserinfoAssertion),
|
handler.NewCol(AppOIDCConfigColumnIDTokenUserinfoAssertion, e.IDTokenUserinfoAssertion),
|
||||||
handler.NewCol(AppOIDCConfigColumnClockSkew, e.ClockSkew),
|
handler.NewCol(AppOIDCConfigColumnClockSkew, e.ClockSkew),
|
||||||
handler.NewCol(AppOIDCConfigColumnAdditionalOrigins, database.StringArray(e.AdditionalOrigins)),
|
handler.NewCol(AppOIDCConfigColumnAdditionalOrigins, database.StringArray(e.AdditionalOrigins)),
|
||||||
|
handler.NewCol(AppOIDCConfigColumnSkipNativeAppSuccessPage, e.SkipNativeAppSuccessPage),
|
||||||
},
|
},
|
||||||
crdb.WithTableSuffix(appOIDCTableSuffix),
|
crdb.WithTableSuffix(appOIDCTableSuffix),
|
||||||
),
|
),
|
||||||
@ -528,6 +531,9 @@ func (p *appProjection) reduceOIDCConfigChanged(event eventstore.Event) (*handle
|
|||||||
if e.AdditionalOrigins != nil {
|
if e.AdditionalOrigins != nil {
|
||||||
cols = append(cols, handler.NewCol(AppOIDCConfigColumnAdditionalOrigins, database.StringArray(*e.AdditionalOrigins)))
|
cols = append(cols, handler.NewCol(AppOIDCConfigColumnAdditionalOrigins, database.StringArray(*e.AdditionalOrigins)))
|
||||||
}
|
}
|
||||||
|
if e.SkipNativeAppSuccessPage != nil {
|
||||||
|
cols = append(cols, handler.NewCol(AppOIDCConfigColumnSkipNativeAppSuccessPage, *e.SkipNativeAppSuccessPage))
|
||||||
|
}
|
||||||
|
|
||||||
if len(cols) == 0 {
|
if len(cols) == 0 {
|
||||||
return crdb.NewNoOpStatement(e), nil
|
return crdb.NewNoOpStatement(e), nil
|
||||||
|
@ -45,7 +45,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "INSERT INTO projections.apps4 (id, name, project_id, creation_date, change_date, resource_owner, instance_id, state, sequence) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
expectedStmt: "INSERT INTO projections.apps5 (id, name, project_id, creation_date, change_date, resource_owner, instance_id, state, sequence) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
"app-id",
|
"app-id",
|
||||||
"my-app",
|
"my-app",
|
||||||
@ -82,7 +82,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.apps4 SET (name, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
expectedStmt: "UPDATE projections.apps5 SET (name, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
"my-app",
|
"my-app",
|
||||||
anyArg{},
|
anyArg{},
|
||||||
@ -95,6 +95,27 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "project reduceAppChanged no change",
|
||||||
|
args: args{
|
||||||
|
event: getEvent(testEvent(
|
||||||
|
repository.EventType(project.ApplicationChangedType),
|
||||||
|
project.AggregateType,
|
||||||
|
[]byte(`{
|
||||||
|
"appId": "app-id"
|
||||||
|
}`),
|
||||||
|
), project.ApplicationChangedEventMapper),
|
||||||
|
},
|
||||||
|
reduce: (&appProjection{}).reduceAppChanged,
|
||||||
|
want: wantReduce{
|
||||||
|
aggregateType: eventstore.AggregateType("project"),
|
||||||
|
sequence: 15,
|
||||||
|
previousSequence: 10,
|
||||||
|
executer: &testExecuter{
|
||||||
|
executions: []execution{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "project reduceAppDeactivated",
|
name: "project reduceAppDeactivated",
|
||||||
args: args{
|
args: args{
|
||||||
@ -114,7 +135,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.apps4 SET (state, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
expectedStmt: "UPDATE projections.apps5 SET (state, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
domain.AppStateInactive,
|
domain.AppStateInactive,
|
||||||
anyArg{},
|
anyArg{},
|
||||||
@ -146,7 +167,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.apps4 SET (state, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
expectedStmt: "UPDATE projections.apps5 SET (state, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
domain.AppStateActive,
|
domain.AppStateActive,
|
||||||
anyArg{},
|
anyArg{},
|
||||||
@ -178,7 +199,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "DELETE FROM projections.apps4 WHERE (id = $1) AND (instance_id = $2)",
|
expectedStmt: "DELETE FROM projections.apps5 WHERE (id = $1) AND (instance_id = $2)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
"app-id",
|
"app-id",
|
||||||
"instance-id",
|
"instance-id",
|
||||||
@ -205,7 +226,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "DELETE FROM projections.apps4 WHERE (project_id = $1) AND (instance_id = $2)",
|
expectedStmt: "DELETE FROM projections.apps5 WHERE (project_id = $1) AND (instance_id = $2)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
"agg-id",
|
"agg-id",
|
||||||
"instance-id",
|
"instance-id",
|
||||||
@ -232,7 +253,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "DELETE FROM projections.apps4 WHERE (instance_id = $1)",
|
expectedStmt: "DELETE FROM projections.apps5 WHERE (instance_id = $1)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
"agg-id",
|
"agg-id",
|
||||||
},
|
},
|
||||||
@ -263,7 +284,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "INSERT INTO projections.apps4_api_configs (app_id, instance_id, client_id, client_secret, auth_method) VALUES ($1, $2, $3, $4, $5)",
|
expectedStmt: "INSERT INTO projections.apps5_api_configs (app_id, instance_id, client_id, client_secret, auth_method) VALUES ($1, $2, $3, $4, $5)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
"app-id",
|
"app-id",
|
||||||
"instance-id",
|
"instance-id",
|
||||||
@ -273,7 +294,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.apps4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
expectedStmt: "UPDATE projections.apps5 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
anyArg{},
|
anyArg{},
|
||||||
uint64(15),
|
uint64(15),
|
||||||
@ -307,7 +328,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.apps4_api_configs SET (client_secret, auth_method) = ($1, $2) WHERE (app_id = $3) AND (instance_id = $4)",
|
expectedStmt: "UPDATE projections.apps5_api_configs SET (client_secret, auth_method) = ($1, $2) WHERE (app_id = $3) AND (instance_id = $4)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
anyArg{},
|
anyArg{},
|
||||||
domain.APIAuthMethodTypePrivateKeyJWT,
|
domain.APIAuthMethodTypePrivateKeyJWT,
|
||||||
@ -316,7 +337,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.apps4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
expectedStmt: "UPDATE projections.apps5 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
anyArg{},
|
anyArg{},
|
||||||
uint64(15),
|
uint64(15),
|
||||||
@ -369,7 +390,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.apps4_api_configs SET client_secret = $1 WHERE (app_id = $2) AND (instance_id = $3)",
|
expectedStmt: "UPDATE projections.apps5_api_configs SET client_secret = $1 WHERE (app_id = $2) AND (instance_id = $3)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
anyArg{},
|
anyArg{},
|
||||||
"app-id",
|
"app-id",
|
||||||
@ -377,7 +398,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.apps4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
expectedStmt: "UPDATE projections.apps5 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
anyArg{},
|
anyArg{},
|
||||||
uint64(15),
|
uint64(15),
|
||||||
@ -412,7 +433,8 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
"idTokenRoleAssertion": true,
|
"idTokenRoleAssertion": true,
|
||||||
"idTokenUserinfoAssertion": true,
|
"idTokenUserinfoAssertion": true,
|
||||||
"clockSkew": 1000,
|
"clockSkew": 1000,
|
||||||
"additionalOrigins": ["origin.one.ch", "origin.two.ch"]
|
"additionalOrigins": ["origin.one.ch", "origin.two.ch"],
|
||||||
|
"skipNativeAppSuccessPage": true
|
||||||
}`),
|
}`),
|
||||||
), project.OIDCConfigAddedEventMapper),
|
), project.OIDCConfigAddedEventMapper),
|
||||||
},
|
},
|
||||||
@ -424,7 +446,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "INSERT INTO projections.apps4_oidc_configs (app_id, instance_id, version, client_id, client_secret, redirect_uris, response_types, grant_types, application_type, auth_method_type, post_logout_redirect_uris, is_dev_mode, access_token_type, access_token_role_assertion, id_token_role_assertion, id_token_userinfo_assertion, clock_skew, additional_origins) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18)",
|
expectedStmt: "INSERT INTO projections.apps5_oidc_configs (app_id, instance_id, version, client_id, client_secret, redirect_uris, response_types, grant_types, application_type, auth_method_type, post_logout_redirect_uris, is_dev_mode, access_token_type, access_token_role_assertion, id_token_role_assertion, id_token_userinfo_assertion, clock_skew, additional_origins, skip_native_app_success_page) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
"app-id",
|
"app-id",
|
||||||
"instance-id",
|
"instance-id",
|
||||||
@ -444,10 +466,11 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
true,
|
true,
|
||||||
1 * time.Microsecond,
|
1 * time.Microsecond,
|
||||||
database.StringArray{"origin.one.ch", "origin.two.ch"},
|
database.StringArray{"origin.one.ch", "origin.two.ch"},
|
||||||
|
true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.apps4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
expectedStmt: "UPDATE projections.apps5 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
anyArg{},
|
anyArg{},
|
||||||
uint64(15),
|
uint64(15),
|
||||||
@ -480,7 +503,9 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
"idTokenRoleAssertion": true,
|
"idTokenRoleAssertion": true,
|
||||||
"idTokenUserinfoAssertion": true,
|
"idTokenUserinfoAssertion": true,
|
||||||
"clockSkew": 1000,
|
"clockSkew": 1000,
|
||||||
"additionalOrigins": ["origin.one.ch", "origin.two.ch"]
|
"additionalOrigins": ["origin.one.ch", "origin.two.ch"],
|
||||||
|
"skipNativeAppSuccessPage": true
|
||||||
|
|
||||||
}`),
|
}`),
|
||||||
), project.OIDCConfigChangedEventMapper),
|
), project.OIDCConfigChangedEventMapper),
|
||||||
},
|
},
|
||||||
@ -492,7 +517,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.apps4_oidc_configs SET (version, redirect_uris, response_types, grant_types, application_type, auth_method_type, post_logout_redirect_uris, is_dev_mode, access_token_type, access_token_role_assertion, id_token_role_assertion, id_token_userinfo_assertion, clock_skew, additional_origins) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) WHERE (app_id = $15) AND (instance_id = $16)",
|
expectedStmt: "UPDATE projections.apps5_oidc_configs SET (version, redirect_uris, response_types, grant_types, application_type, auth_method_type, post_logout_redirect_uris, is_dev_mode, access_token_type, access_token_role_assertion, id_token_role_assertion, id_token_userinfo_assertion, clock_skew, additional_origins, skip_native_app_success_page) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) WHERE (app_id = $16) AND (instance_id = $17)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
domain.OIDCVersionV1,
|
domain.OIDCVersionV1,
|
||||||
database.StringArray{"redirect.one.ch", "redirect.two.ch"},
|
database.StringArray{"redirect.one.ch", "redirect.two.ch"},
|
||||||
@ -508,12 +533,13 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
true,
|
true,
|
||||||
1 * time.Microsecond,
|
1 * time.Microsecond,
|
||||||
database.StringArray{"origin.one.ch", "origin.two.ch"},
|
database.StringArray{"origin.one.ch", "origin.two.ch"},
|
||||||
|
true,
|
||||||
"app-id",
|
"app-id",
|
||||||
"instance-id",
|
"instance-id",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.apps4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
expectedStmt: "UPDATE projections.apps5 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
anyArg{},
|
anyArg{},
|
||||||
uint64(15),
|
uint64(15),
|
||||||
@ -566,7 +592,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.apps4_oidc_configs SET client_secret = $1 WHERE (app_id = $2) AND (instance_id = $3)",
|
expectedStmt: "UPDATE projections.apps5_oidc_configs SET client_secret = $1 WHERE (app_id = $2) AND (instance_id = $3)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
anyArg{},
|
anyArg{},
|
||||||
"app-id",
|
"app-id",
|
||||||
@ -574,7 +600,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.apps4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
expectedStmt: "UPDATE projections.apps5 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
anyArg{},
|
anyArg{},
|
||||||
uint64(15),
|
uint64(15),
|
||||||
@ -603,7 +629,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.apps4 SET (change_date, sequence, owner_removed) = ($1, $2, $3) WHERE (instance_id = $4) AND (resource_owner = $5)",
|
expectedStmt: "UPDATE projections.apps5 SET (change_date, sequence, owner_removed) = ($1, $2, $3) WHERE (instance_id = $4) AND (resource_owner = $5)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
anyArg{},
|
anyArg{},
|
||||||
uint64(15),
|
uint64(15),
|
||||||
|
@ -40,6 +40,7 @@ type OIDCConfigAddedEvent struct {
|
|||||||
IDTokenUserinfoAssertion bool `json:"idTokenUserinfoAssertion,omitempty"`
|
IDTokenUserinfoAssertion bool `json:"idTokenUserinfoAssertion,omitempty"`
|
||||||
ClockSkew time.Duration `json:"clockSkew,omitempty"`
|
ClockSkew time.Duration `json:"clockSkew,omitempty"`
|
||||||
AdditionalOrigins []string `json:"additionalOrigins,omitempty"`
|
AdditionalOrigins []string `json:"additionalOrigins,omitempty"`
|
||||||
|
SkipNativeAppSuccessPage bool `json:"skipNativeAppSuccessPage,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *OIDCConfigAddedEvent) Data() interface{} {
|
func (e *OIDCConfigAddedEvent) Data() interface{} {
|
||||||
@ -70,6 +71,7 @@ func NewOIDCConfigAddedEvent(
|
|||||||
idTokenUserinfoAssertion bool,
|
idTokenUserinfoAssertion bool,
|
||||||
clockSkew time.Duration,
|
clockSkew time.Duration,
|
||||||
additionalOrigins []string,
|
additionalOrigins []string,
|
||||||
|
skipNativeAppSuccessPage bool,
|
||||||
) *OIDCConfigAddedEvent {
|
) *OIDCConfigAddedEvent {
|
||||||
return &OIDCConfigAddedEvent{
|
return &OIDCConfigAddedEvent{
|
||||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||||
@ -94,6 +96,7 @@ func NewOIDCConfigAddedEvent(
|
|||||||
IDTokenUserinfoAssertion: idTokenUserinfoAssertion,
|
IDTokenUserinfoAssertion: idTokenUserinfoAssertion,
|
||||||
ClockSkew: clockSkew,
|
ClockSkew: clockSkew,
|
||||||
AdditionalOrigins: additionalOrigins,
|
AdditionalOrigins: additionalOrigins,
|
||||||
|
SkipNativeAppSuccessPage: skipNativeAppSuccessPage,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,8 +182,7 @@ func (e *OIDCConfigAddedEvent) Validate(cmd eventstore.Command) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return e.SkipNativeAppSuccessPage == c.SkipNativeAppSuccessPage
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func OIDCConfigAddedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
func OIDCConfigAddedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||||
@ -214,6 +216,7 @@ type OIDCConfigChangedEvent struct {
|
|||||||
IDTokenUserinfoAssertion *bool `json:"idTokenUserinfoAssertion,omitempty"`
|
IDTokenUserinfoAssertion *bool `json:"idTokenUserinfoAssertion,omitempty"`
|
||||||
ClockSkew *time.Duration `json:"clockSkew,omitempty"`
|
ClockSkew *time.Duration `json:"clockSkew,omitempty"`
|
||||||
AdditionalOrigins *[]string `json:"additionalOrigins,omitempty"`
|
AdditionalOrigins *[]string `json:"additionalOrigins,omitempty"`
|
||||||
|
SkipNativeAppSuccessPage *bool `json:"skipNativeAppSuccessPage,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *OIDCConfigChangedEvent) Data() interface{} {
|
func (e *OIDCConfigChangedEvent) Data() interface{} {
|
||||||
@ -334,6 +337,12 @@ func ChangeAdditionalOrigins(additionalOrigins []string) func(event *OIDCConfigC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ChangeSkipNativeAppSuccessPage(skipNativeAppSuccessPage bool) func(event *OIDCConfigChangedEvent) {
|
||||||
|
return func(e *OIDCConfigChangedEvent) {
|
||||||
|
e.SkipNativeAppSuccessPage = &skipNativeAppSuccessPage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func OIDCConfigChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
func OIDCConfigChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||||
e := &OIDCConfigChangedEvent{
|
e := &OIDCConfigChangedEvent{
|
||||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
@ -163,6 +163,11 @@ message OIDCConfig {
|
|||||||
description: "all allowed origins from where the API can be used";
|
description: "all allowed origins from where the API can be used";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
bool skip_native_app_success_page = 20 [
|
||||||
|
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||||
|
description: "Skip the successful login page on native apps and directly redirect the user to the callback.";
|
||||||
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
enum OIDCResponseType {
|
enum OIDCResponseType {
|
||||||
|
@ -8773,6 +8773,11 @@ message AddOIDCAppRequest {
|
|||||||
description: "Additional origins (other than the redirect_uris) from where the API can be used";
|
description: "Additional origins (other than the redirect_uris) from where the API can be used";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
bool skip_native_app_success_page = 17 [
|
||||||
|
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||||
|
description: "Skip the successful login page on native apps and directly redirect the user to the callback.";
|
||||||
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
message AddOIDCAppResponse {
|
message AddOIDCAppResponse {
|
||||||
@ -8943,6 +8948,11 @@ message UpdateOIDCAppConfigRequest {
|
|||||||
description: "Additional origins (other than the redirect_uris) from where the API can be used";
|
description: "Additional origins (other than the redirect_uris) from where the API can be used";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
bool skip_native_app_success_page = 16 [
|
||||||
|
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||||
|
description: "Skip the successful login page on native apps and directly redirect the user to the callback.";
|
||||||
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
message UpdateOIDCAppConfigResponse {
|
message UpdateOIDCAppConfigResponse {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user