mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 21:37:24 +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
b3d8787921
commit
8bf36301ed
@ -306,7 +306,7 @@
|
||||
</span>
|
||||
<span class="right">
|
||||
<span>
|
||||
{{ 'APP.API.AUTHMETHOD.' + authMethodType?.value | translate }}
|
||||
{{ 'APP.API.AUTHMETHOD.' + apiAppRequest.toObject().authMethodType | translate }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -331,11 +331,24 @@
|
||||
</div>
|
||||
</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
|
||||
*ngIf="appType?.value !== undefined"
|
||||
class="redirect-section"
|
||||
[disabled]="!canWrite"
|
||||
[devMode]="devMode?.value"
|
||||
[devMode]="!!devMode?.value"
|
||||
[(ngModel)]="redirectUrisList"
|
||||
title="{{ 'APP.OIDC.REDIRECT' | translate }}"
|
||||
[isNative]="appType?.value === OIDCAppType.OIDC_APP_TYPE_NATIVE"
|
||||
@ -346,7 +359,7 @@
|
||||
*ngIf="appType?.value !== undefined"
|
||||
class="redirect-section"
|
||||
[disabled]="!canWrite"
|
||||
[devMode]="devMode?.value"
|
||||
[devMode]="!!devMode?.value"
|
||||
[(ngModel)]="postLogoutRedirectUrisList"
|
||||
title="{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}"
|
||||
[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 { HttpClient } from '@angular/common/http';
|
||||
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 { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
@ -149,7 +149,8 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
private http: HttpClient,
|
||||
) {
|
||||
this.oidcForm = this.fb.group({
|
||||
devMode: [{ value: false, disabled: true }, []],
|
||||
devMode: [{ value: false, disabled: true }],
|
||||
skipNativeAppSuccessPage: [{ value: false, disabled: true }],
|
||||
clientId: [{ value: '', disabled: true }],
|
||||
responseTypesList: [{ 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.postLogoutRedirectUrisList = this.postLogoutRedirectUrisList;
|
||||
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();
|
||||
req.setProjectId(this.projectId);
|
||||
@ -571,6 +573,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
req.setAdditionalOriginsList(this.app.oidcConfig.additionalOriginsList);
|
||||
req.setPostLogoutRedirectUrisList(this.app.oidcConfig.postLogoutRedirectUrisList);
|
||||
req.setDevMode(this.app.oidcConfig.devMode);
|
||||
req.setSkipNativeAppSuccessPage(this.app.oidcConfig.skipNativeAppSuccessPage);
|
||||
|
||||
if (this.clockSkewSeconds?.value) {
|
||||
const dur = new Duration();
|
||||
@ -738,11 +741,15 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public get apiAuthMethodType(): AbstractControl | null {
|
||||
return this.apiForm.get('authMethodType');
|
||||
return this.apiForm.get('authMethodType') as UntypedFormControl;
|
||||
}
|
||||
|
||||
public get devMode(): UntypedFormControl | null {
|
||||
return this.oidcForm.get('devMode') as UntypedFormControl;
|
||||
public get devMode(): FormControl<boolean> | null {
|
||||
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 {
|
||||
|
@ -1937,6 +1937,8 @@
|
||||
"REGENERATESECRET": "Client Secret neu generieren",
|
||||
"DEVMODE": "Entwicklermodus",
|
||||
"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",
|
||||
"REDIRECTSECTION": "Weiterleitungs-URIs",
|
||||
"POSTLOGOUTREDIRECT": "URIs für Post-Log-out",
|
||||
|
@ -1930,6 +1930,8 @@
|
||||
"REGENERATESECRET": "Regenerate Client Secret",
|
||||
"DEVMODE": "Development Mode",
|
||||
"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",
|
||||
"REDIRECTSECTION": "Redirect URIs",
|
||||
"POSTLOGOUTREDIRECT": "Post Logout URIs",
|
||||
|
@ -1938,6 +1938,8 @@
|
||||
"REGENERATESECRET": "Régénérer le secret du client",
|
||||
"DEVMODE": "Mode développement",
|
||||
"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",
|
||||
"REDIRECTSECTION": "URI de redirection",
|
||||
"POSTLOGOUTREDIRECT": "URIs de post-déconnexion",
|
||||
|
@ -1939,6 +1939,8 @@
|
||||
"REGENERATESECRET": "Rigenera il Client Secret",
|
||||
"DEVMODE": "Modalit\u00e0 di sviluppo (DEV Mode)",
|
||||
"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",
|
||||
"REDIRECTSECTION": "Reindirizzamento",
|
||||
"POSTLOGOUTREDIRECT": "URI post logout",
|
||||
|
@ -1929,6 +1929,8 @@
|
||||
"REGENERATESECRET": "クライアントシークレットを再生成する",
|
||||
"DEVMODE": "開発モード",
|
||||
"DEVMODEDESC": "注意:開発モードを有効にすると、URIが認証されません。",
|
||||
"SKIPNATIVEAPPSUCCESSPAGE": "ログイン後に成功ページをスキップする",
|
||||
"SKIPNATIVEAPPSUCCESSPAGE_DESCRIPTION": "このネイティブアプリのログイン後に成功ページをスキップする",
|
||||
"REDIRECT": "リダイレクトURI",
|
||||
"REDIRECTSECTION": "リダイレクトURI",
|
||||
"POSTLOGOUTREDIRECT": "ログアウトURI",
|
||||
|
@ -1938,6 +1938,8 @@
|
||||
"REGENERATESECRET": "Odtwórz sekret klienta",
|
||||
"DEVMODE": "Tryb rozwoju",
|
||||
"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",
|
||||
"REDIRECTSECTION": "Adresy URI przekierowania",
|
||||
"POSTLOGOUTREDIRECT": "Adresy URI po wylogowaniu",
|
||||
|
@ -1937,6 +1937,8 @@
|
||||
"REGENERATESECRET": "重新生成客户端密钥",
|
||||
"DEVMODE": "开发模式",
|
||||
"DEVMODEDESC": "注意:启用开发模式的重定向 URI 将不会被验证。",
|
||||
"SKIPNATIVEAPPSUCCESSPAGE": "登录后跳过成功页面",
|
||||
"SKIPNATIVEAPPSUCCESSPAGE_DESCRIPTION": "登录后跳过本机应用的成功页面",
|
||||
"REDIRECT": "重定向 URLs",
|
||||
"REDIRECTSECTION": "重定向 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.
|
||||
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
|
||||
alt="Redirect URIs"
|
||||
|
@ -800,6 +800,7 @@ func (s *Server) getProjectsAndApps(ctx context.Context, org string) ([]*v1_pb.D
|
||||
IdTokenUserinfoAssertion: app.OIDCConfig.AssertIDTokenUserinfo,
|
||||
ClockSkew: durationpb.New(app.OIDCConfig.ClockSkew),
|
||||
AdditionalOrigins: app.OIDCConfig.AdditionalOrigins,
|
||||
SkipNativeAppSuccessPage: app.OIDCConfig.SkipNativeAppSuccessPage,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ func AddOIDCAppRequestToDomain(req *mgmt_pb.AddOIDCAppRequest) *domain.OIDCApp {
|
||||
IDTokenUserinfoAssertion: req.IdTokenUserinfoAssertion,
|
||||
ClockSkew: req.ClockSkew.AsDuration(),
|
||||
AdditionalOrigins: req.AdditionalOrigins,
|
||||
SkipNativeAppSuccessPage: req.SkipNativeAppSuccessPage,
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,6 +107,7 @@ func UpdateOIDCAppConfigRequestToDomain(app *mgmt_pb.UpdateOIDCAppConfigRequest)
|
||||
IDTokenUserinfoAssertion: app.IdTokenUserinfoAssertion,
|
||||
ClockSkew: app.ClockSkew.AsDuration(),
|
||||
AdditionalOrigins: app.AdditionalOrigins,
|
||||
SkipNativeAppSuccessPage: app.SkipNativeAppSuccessPage,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,6 +60,7 @@ func AppOIDCConfigToPb(app *query.OIDCApp) *app_pb.App_OidcConfig {
|
||||
ClockSkew: durationpb.New(app.ClockSkew),
|
||||
AdditionalOrigins: app.AdditionalOrigins,
|
||||
AllowedOrigins: app.AllowedOrigins,
|
||||
SkipNativeAppSuccessPage: app.SkipNativeAppSuccessPage,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package login
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"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),
|
||||
}
|
||||
if authReq != nil {
|
||||
//the id will be set via the html (maybe change this with the login refactoring)
|
||||
if _, ok := authReq.Request.(*domain.AuthRequestOIDC); ok {
|
||||
data.RedirectURI = l.oidcAuthCallbackURL(r.Context(), "")
|
||||
} else if _, ok := authReq.Request.(*domain.AuthRequestSAML); ok {
|
||||
data.RedirectURI = l.samlAuthCallbackURL(r.Context(), "")
|
||||
data.RedirectURI, err = l.authRequestCallback(r.Context(), authReq)
|
||||
if err != nil {
|
||||
l.renderInternalError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
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) {
|
||||
var callback string
|
||||
switch authReq.Request.(type) {
|
||||
case *domain.AuthRequestOIDC:
|
||||
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"))
|
||||
callback, err := l.authRequestCallback(r.Context(), authReq)
|
||||
if err != nil {
|
||||
l.renderInternalError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
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() {
|
||||
let form = document.getElementsByTagName('form')[0];
|
||||
if (form) {
|
||||
let button = document.getElementById("redirect-button");
|
||||
if (button) {
|
||||
button.addEventListener("click", function (event) {
|
||||
location.reload();
|
||||
event.preventDefault();
|
||||
});
|
||||
}
|
||||
form.submit();
|
||||
}
|
||||
}
|
||||
|
@ -29,4 +29,4 @@
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{template "main-bottom" .}}
|
||||
{{template "main-bottom" .}}
|
||||
|
@ -1223,7 +1223,7 @@ func (repo *AuthRequestRepo) hasSucceededPage(ctx context.Context, request *doma
|
||||
if err != nil {
|
||||
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) {
|
||||
|
@ -161,7 +161,9 @@ func TestCommandSide_AddInstanceDomain(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
time.Second*1,
|
||||
[]string{"https://sub.test.ch"}),
|
||||
[]string{"https://sub.test.ch"},
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
|
@ -19,20 +19,21 @@ import (
|
||||
|
||||
type addOIDCApp struct {
|
||||
AddApp
|
||||
Version domain.OIDCVersion
|
||||
RedirectUris []string
|
||||
ResponseTypes []domain.OIDCResponseType
|
||||
GrantTypes []domain.OIDCGrantType
|
||||
ApplicationType domain.OIDCApplicationType
|
||||
AuthMethodType domain.OIDCAuthMethodType
|
||||
PostLogoutRedirectUris []string
|
||||
DevMode bool
|
||||
AccessTokenType domain.OIDCTokenType
|
||||
AccessTokenRoleAssertion bool
|
||||
IDTokenRoleAssertion bool
|
||||
IDTokenUserinfoAssertion bool
|
||||
ClockSkew time.Duration
|
||||
AdditionalOrigins []string
|
||||
Version domain.OIDCVersion
|
||||
RedirectUris []string
|
||||
ResponseTypes []domain.OIDCResponseType
|
||||
GrantTypes []domain.OIDCGrantType
|
||||
ApplicationType domain.OIDCApplicationType
|
||||
AuthMethodType domain.OIDCAuthMethodType
|
||||
PostLogoutRedirectUris []string
|
||||
DevMode bool
|
||||
AccessTokenType domain.OIDCTokenType
|
||||
AccessTokenRoleAssertion bool
|
||||
IDTokenRoleAssertion bool
|
||||
IDTokenUserinfoAssertion bool
|
||||
ClockSkew time.Duration
|
||||
AdditionalOrigins []string
|
||||
SkipSuccessPageForNativeApp bool
|
||||
|
||||
ClientID string
|
||||
ClientSecret *crypto.CryptoValue
|
||||
@ -109,6 +110,7 @@ func (c *Commands) AddOIDCAppCommand(app *addOIDCApp, clientSecretAlg crypto.Has
|
||||
app.IDTokenUserinfoAssertion,
|
||||
app.ClockSkew,
|
||||
app.AdditionalOrigins,
|
||||
app.SkipSuccessPageForNativeApp,
|
||||
),
|
||||
}, nil
|
||||
}, nil
|
||||
@ -191,7 +193,9 @@ func (c *Commands) addOIDCApplicationWithID(ctx context.Context, oidcApp *domain
|
||||
oidcApp.IDTokenRoleAssertion,
|
||||
oidcApp.IDTokenUserinfoAssertion,
|
||||
oidcApp.ClockSkew,
|
||||
oidcApp.AdditionalOrigins))
|
||||
oidcApp.AdditionalOrigins,
|
||||
oidcApp.SkipNativeAppSuccessPage,
|
||||
))
|
||||
|
||||
addedApplication.AppID = oidcApp.AppID
|
||||
pushedEvents, err := c.eventstore.Push(ctx, events...)
|
||||
@ -241,7 +245,9 @@ func (c *Commands) ChangeOIDCApplication(ctx context.Context, oidc *domain.OIDCA
|
||||
oidc.IDTokenRoleAssertion,
|
||||
oidc.IDTokenUserinfoAssertion,
|
||||
oidc.ClockSkew,
|
||||
oidc.AdditionalOrigins)
|
||||
oidc.AdditionalOrigins,
|
||||
oidc.SkipNativeAppSuccessPage,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ type OIDCApplicationWriteModel struct {
|
||||
ClockSkew time.Duration
|
||||
State domain.AppState
|
||||
AdditionalOrigins []string
|
||||
SkipNativeAppSuccessPage bool
|
||||
oidc bool
|
||||
}
|
||||
|
||||
@ -156,6 +157,7 @@ func (wm *OIDCApplicationWriteModel) appendAddOIDCEvent(e *project.OIDCConfigAdd
|
||||
wm.IDTokenUserinfoAssertion = e.IDTokenUserinfoAssertion
|
||||
wm.ClockSkew = e.ClockSkew
|
||||
wm.AdditionalOrigins = e.AdditionalOrigins
|
||||
wm.SkipNativeAppSuccessPage = e.SkipNativeAppSuccessPage
|
||||
}
|
||||
|
||||
func (wm *OIDCApplicationWriteModel) appendChangeOIDCEvent(e *project.OIDCConfigChangedEvent) {
|
||||
@ -201,6 +203,9 @@ func (wm *OIDCApplicationWriteModel) appendChangeOIDCEvent(e *project.OIDCConfig
|
||||
if e.AdditionalOrigins != nil {
|
||||
wm.AdditionalOrigins = *e.AdditionalOrigins
|
||||
}
|
||||
if e.SkipNativeAppSuccessPage != nil {
|
||||
wm.SkipNativeAppSuccessPage = *e.SkipNativeAppSuccessPage
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OIDCApplicationWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
@ -240,6 +245,7 @@ func (wm *OIDCApplicationWriteModel) NewChangedEvent(
|
||||
idTokenUserinfoAssertion bool,
|
||||
clockSkew time.Duration,
|
||||
additionalOrigins []string,
|
||||
skipNativeAppSuccessPage bool,
|
||||
) (*project.OIDCConfigChangedEvent, bool, error) {
|
||||
changes := make([]project.OIDCConfigChanges, 0)
|
||||
var err error
|
||||
@ -286,6 +292,10 @@ func (wm *OIDCApplicationWriteModel) NewChangedEvent(
|
||||
if !reflect.DeepEqual(wm.AdditionalOrigins, additionalOrigins) {
|
||||
changes = append(changes, project.ChangeAdditionalOrigins(additionalOrigins))
|
||||
}
|
||||
if wm.SkipNativeAppSuccessPage != skipNativeAppSuccessPage {
|
||||
changes = append(changes, project.ChangeSkipNativeAppSuccessPage(skipNativeAppSuccessPage))
|
||||
}
|
||||
|
||||
if len(changes) == 0 {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
@ -169,6 +169,7 @@ func TestAddOIDCApp(t *testing.T) {
|
||||
false,
|
||||
0,
|
||||
nil,
|
||||
false,
|
||||
),
|
||||
},
|
||||
},
|
||||
@ -325,7 +326,9 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
time.Second*1,
|
||||
[]string{"https://sub.test.ch"}),
|
||||
[]string{"https://sub.test.ch"},
|
||||
true,
|
||||
),
|
||||
),
|
||||
},
|
||||
uniqueConstraintsFromEventConstraint(project.NewAddApplicationUniqueConstraint("app", "project1")),
|
||||
@ -354,6 +357,7 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
|
||||
IDTokenUserinfoAssertion: true,
|
||||
ClockSkew: time.Second * 1,
|
||||
AdditionalOrigins: []string{"https://sub.test.ch"},
|
||||
SkipNativeAppSuccessPage: true,
|
||||
},
|
||||
resourceOwner: "org1",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
@ -382,6 +386,7 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
|
||||
IDTokenUserinfoAssertion: true,
|
||||
ClockSkew: time.Second * 1,
|
||||
AdditionalOrigins: []string{"https://sub.test.ch"},
|
||||
SkipNativeAppSuccessPage: true,
|
||||
State: domain.AppStateActive,
|
||||
Compliance: &domain.Compliance{},
|
||||
},
|
||||
@ -558,7 +563,9 @@ func TestCommandSide_ChangeOIDCApplication(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
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,
|
||||
ClockSkew: time.Second * 1,
|
||||
AdditionalOrigins: []string{"https://sub.test.ch"},
|
||||
SkipNativeAppSuccessPage: true,
|
||||
},
|
||||
resourceOwner: "org1",
|
||||
},
|
||||
@ -629,7 +637,9 @@ func TestCommandSide_ChangeOIDCApplication(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
time.Second*1,
|
||||
[]string{"https://sub.test.ch"}),
|
||||
[]string{"https://sub.test.ch"},
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
@ -666,6 +676,7 @@ func TestCommandSide_ChangeOIDCApplication(t *testing.T) {
|
||||
IDTokenUserinfoAssertion: false,
|
||||
ClockSkew: time.Second * 2,
|
||||
AdditionalOrigins: []string{"https://sub.test.ch"},
|
||||
SkipNativeAppSuccessPage: true,
|
||||
},
|
||||
resourceOwner: "org1",
|
||||
},
|
||||
@ -692,6 +703,7 @@ func TestCommandSide_ChangeOIDCApplication(t *testing.T) {
|
||||
IDTokenUserinfoAssertion: false,
|
||||
ClockSkew: time.Second * 2,
|
||||
AdditionalOrigins: []string{"https://sub.test.ch"},
|
||||
SkipNativeAppSuccessPage: true,
|
||||
Compliance: &domain.Compliance{},
|
||||
State: domain.AppStateActive,
|
||||
},
|
||||
@ -826,7 +838,9 @@ func TestCommandSide_ChangeOIDCApplicationSecret(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
time.Second*1,
|
||||
[]string{"https://sub.test.ch"}),
|
||||
[]string{"https://sub.test.ch"},
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
@ -877,6 +891,7 @@ func TestCommandSide_ChangeOIDCApplicationSecret(t *testing.T) {
|
||||
IDTokenUserinfoAssertion: true,
|
||||
ClockSkew: time.Second * 1,
|
||||
AdditionalOrigins: []string{"https://sub.test.ch"},
|
||||
SkipNativeAppSuccessPage: false,
|
||||
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 {
|
||||
return &domain.OIDCApp{
|
||||
ObjectRoot: writeModelToObjectRoot(writeModel.WriteModel),
|
||||
@ -54,6 +46,7 @@ func oidcWriteModelToOIDCConfig(writeModel *OIDCApplicationWriteModel) *domain.O
|
||||
IDTokenUserinfoAssertion: writeModel.IDTokenUserinfoAssertion,
|
||||
ClockSkew: writeModel.ClockSkew,
|
||||
AdditionalOrigins: writeModel.AdditionalOrigins,
|
||||
SkipNativeAppSuccessPage: writeModel.SkipNativeAppSuccessPage,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,9 +3,9 @@ package command
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
caos_errs "github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
|
@ -45,6 +45,7 @@ type OIDCApp struct {
|
||||
IDTokenUserinfoAssertion bool
|
||||
ClockSkew time.Duration
|
||||
AdditionalOrigins []string
|
||||
SkipNativeAppSuccessPage bool
|
||||
|
||||
State AppState
|
||||
}
|
||||
|
@ -40,23 +40,24 @@ type App struct {
|
||||
}
|
||||
|
||||
type OIDCApp struct {
|
||||
RedirectURIs database.StringArray
|
||||
ResponseTypes database.EnumArray[domain.OIDCResponseType]
|
||||
GrantTypes database.EnumArray[domain.OIDCGrantType]
|
||||
AppType domain.OIDCApplicationType
|
||||
ClientID string
|
||||
AuthMethodType domain.OIDCAuthMethodType
|
||||
PostLogoutRedirectURIs database.StringArray
|
||||
Version domain.OIDCVersion
|
||||
ComplianceProblems database.StringArray
|
||||
IsDevMode bool
|
||||
AccessTokenType domain.OIDCTokenType
|
||||
AssertAccessTokenRole bool
|
||||
AssertIDTokenRole bool
|
||||
AssertIDTokenUserinfo bool
|
||||
ClockSkew time.Duration
|
||||
AdditionalOrigins database.StringArray
|
||||
AllowedOrigins database.StringArray
|
||||
RedirectURIs database.StringArray
|
||||
ResponseTypes database.EnumArray[domain.OIDCResponseType]
|
||||
GrantTypes database.EnumArray[domain.OIDCGrantType]
|
||||
AppType domain.OIDCApplicationType
|
||||
ClientID string
|
||||
AuthMethodType domain.OIDCAuthMethodType
|
||||
PostLogoutRedirectURIs database.StringArray
|
||||
Version domain.OIDCVersion
|
||||
ComplianceProblems database.StringArray
|
||||
IsDevMode bool
|
||||
AccessTokenType domain.OIDCTokenType
|
||||
AssertAccessTokenRole bool
|
||||
AssertIDTokenRole bool
|
||||
AssertIDTokenUserinfo bool
|
||||
ClockSkew time.Duration
|
||||
AdditionalOrigins database.StringArray
|
||||
AllowedOrigins database.StringArray
|
||||
SkipNativeAppSuccessPage bool
|
||||
}
|
||||
|
||||
type SAMLApp struct {
|
||||
@ -241,6 +242,10 @@ var (
|
||||
name: projection.AppOIDCConfigColumnAdditionalOrigins,
|
||||
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) {
|
||||
@ -535,6 +540,7 @@ func prepareAppQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder,
|
||||
AppOIDCConfigColumnIDTokenUserinfoAssertion.identifier(),
|
||||
AppOIDCConfigColumnClockSkew.identifier(),
|
||||
AppOIDCConfigColumnAdditionalOrigins.identifier(),
|
||||
AppOIDCConfigColumnSkipNativeAppSuccessPage.identifier(),
|
||||
|
||||
AppSAMLConfigColumnAppID.identifier(),
|
||||
AppSAMLConfigColumnEntityID.identifier(),
|
||||
@ -583,6 +589,7 @@ func prepareAppQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder,
|
||||
&oidcConfig.iDTokenUserinfoAssertion,
|
||||
&oidcConfig.clockSkew,
|
||||
&oidcConfig.additionalOrigins,
|
||||
&oidcConfig.skipNativeAppSuccessPage,
|
||||
|
||||
&samlConfig.appID,
|
||||
&samlConfig.entityID,
|
||||
@ -703,6 +710,7 @@ func prepareAppsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder
|
||||
AppOIDCConfigColumnIDTokenUserinfoAssertion.identifier(),
|
||||
AppOIDCConfigColumnClockSkew.identifier(),
|
||||
AppOIDCConfigColumnAdditionalOrigins.identifier(),
|
||||
AppOIDCConfigColumnSkipNativeAppSuccessPage.identifier(),
|
||||
|
||||
AppSAMLConfigColumnAppID.identifier(),
|
||||
AppSAMLConfigColumnEntityID.identifier(),
|
||||
@ -754,6 +762,7 @@ func prepareAppsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder
|
||||
&oidcConfig.iDTokenUserinfoAssertion,
|
||||
&oidcConfig.clockSkew,
|
||||
&oidcConfig.additionalOrigins,
|
||||
&oidcConfig.skipNativeAppSuccessPage,
|
||||
|
||||
&samlConfig.appID,
|
||||
&samlConfig.entityID,
|
||||
@ -825,6 +834,7 @@ type sqlOIDCConfig struct {
|
||||
additionalOrigins database.StringArray
|
||||
responseTypes database.EnumArray[domain.OIDCResponseType]
|
||||
grantTypes database.EnumArray[domain.OIDCGrantType]
|
||||
skipNativeAppSuccessPage sql.NullBool
|
||||
}
|
||||
|
||||
func (c sqlOIDCConfig) set(app *App) {
|
||||
@ -832,21 +842,22 @@ func (c sqlOIDCConfig) set(app *App) {
|
||||
return
|
||||
}
|
||||
app.OIDCConfig = &OIDCApp{
|
||||
Version: domain.OIDCVersion(c.version.Int32),
|
||||
ClientID: c.clientID.String,
|
||||
RedirectURIs: c.redirectUris,
|
||||
AppType: domain.OIDCApplicationType(c.applicationType.Int16),
|
||||
AuthMethodType: domain.OIDCAuthMethodType(c.authMethodType.Int16),
|
||||
PostLogoutRedirectURIs: c.postLogoutRedirectUris,
|
||||
IsDevMode: c.devMode.Bool,
|
||||
AccessTokenType: domain.OIDCTokenType(c.accessTokenType.Int16),
|
||||
AssertAccessTokenRole: c.accessTokenRoleAssertion.Bool,
|
||||
AssertIDTokenRole: c.iDTokenRoleAssertion.Bool,
|
||||
AssertIDTokenUserinfo: c.iDTokenUserinfoAssertion.Bool,
|
||||
ClockSkew: time.Duration(c.clockSkew.Int64),
|
||||
AdditionalOrigins: c.additionalOrigins,
|
||||
ResponseTypes: c.responseTypes,
|
||||
GrantTypes: c.grantTypes,
|
||||
Version: domain.OIDCVersion(c.version.Int32),
|
||||
ClientID: c.clientID.String,
|
||||
RedirectURIs: c.redirectUris,
|
||||
AppType: domain.OIDCApplicationType(c.applicationType.Int16),
|
||||
AuthMethodType: domain.OIDCAuthMethodType(c.authMethodType.Int16),
|
||||
PostLogoutRedirectURIs: c.postLogoutRedirectUris,
|
||||
IsDevMode: c.devMode.Bool,
|
||||
AccessTokenType: domain.OIDCTokenType(c.accessTokenType.Int16),
|
||||
AssertAccessTokenRole: c.accessTokenRoleAssertion.Bool,
|
||||
AssertIDTokenRole: c.iDTokenRoleAssertion.Bool,
|
||||
AssertIDTokenUserinfo: c.iDTokenUserinfoAssertion.Bool,
|
||||
ClockSkew: time.Duration(c.clockSkew.Int64),
|
||||
AdditionalOrigins: c.additionalOrigins,
|
||||
ResponseTypes: c.responseTypes,
|
||||
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)
|
||||
app.OIDCConfig.ComplianceProblems = compliance.Problems
|
||||
|
@ -15,96 +15,98 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
expectedAppQuery = regexp.QuoteMeta(`SELECT projections.apps4.id,` +
|
||||
` projections.apps4.name,` +
|
||||
` projections.apps4.project_id,` +
|
||||
` projections.apps4.creation_date,` +
|
||||
` projections.apps4.change_date,` +
|
||||
` projections.apps4.resource_owner,` +
|
||||
` projections.apps4.state,` +
|
||||
` projections.apps4.sequence,` +
|
||||
expectedAppQuery = regexp.QuoteMeta(`SELECT projections.apps5.id,` +
|
||||
` projections.apps5.name,` +
|
||||
` projections.apps5.project_id,` +
|
||||
` projections.apps5.creation_date,` +
|
||||
` projections.apps5.change_date,` +
|
||||
` projections.apps5.resource_owner,` +
|
||||
` projections.apps5.state,` +
|
||||
` projections.apps5.sequence,` +
|
||||
// api config
|
||||
` projections.apps4_api_configs.app_id,` +
|
||||
` projections.apps4_api_configs.client_id,` +
|
||||
` projections.apps4_api_configs.auth_method,` +
|
||||
` projections.apps5_api_configs.app_id,` +
|
||||
` projections.apps5_api_configs.client_id,` +
|
||||
` projections.apps5_api_configs.auth_method,` +
|
||||
// oidc config
|
||||
` projections.apps4_oidc_configs.app_id,` +
|
||||
` projections.apps4_oidc_configs.version,` +
|
||||
` projections.apps4_oidc_configs.client_id,` +
|
||||
` projections.apps4_oidc_configs.redirect_uris,` +
|
||||
` projections.apps4_oidc_configs.response_types,` +
|
||||
` projections.apps4_oidc_configs.grant_types,` +
|
||||
` projections.apps4_oidc_configs.application_type,` +
|
||||
` projections.apps4_oidc_configs.auth_method_type,` +
|
||||
` projections.apps4_oidc_configs.post_logout_redirect_uris,` +
|
||||
` projections.apps4_oidc_configs.is_dev_mode,` +
|
||||
` projections.apps4_oidc_configs.access_token_type,` +
|
||||
` projections.apps4_oidc_configs.access_token_role_assertion,` +
|
||||
` projections.apps4_oidc_configs.id_token_role_assertion,` +
|
||||
` projections.apps4_oidc_configs.id_token_userinfo_assertion,` +
|
||||
` projections.apps4_oidc_configs.clock_skew,` +
|
||||
` projections.apps4_oidc_configs.additional_origins,` +
|
||||
` projections.apps5_oidc_configs.app_id,` +
|
||||
` projections.apps5_oidc_configs.version,` +
|
||||
` projections.apps5_oidc_configs.client_id,` +
|
||||
` projections.apps5_oidc_configs.redirect_uris,` +
|
||||
` projections.apps5_oidc_configs.response_types,` +
|
||||
` projections.apps5_oidc_configs.grant_types,` +
|
||||
` projections.apps5_oidc_configs.application_type,` +
|
||||
` projections.apps5_oidc_configs.auth_method_type,` +
|
||||
` projections.apps5_oidc_configs.post_logout_redirect_uris,` +
|
||||
` projections.apps5_oidc_configs.is_dev_mode,` +
|
||||
` projections.apps5_oidc_configs.access_token_type,` +
|
||||
` projections.apps5_oidc_configs.access_token_role_assertion,` +
|
||||
` projections.apps5_oidc_configs.id_token_role_assertion,` +
|
||||
` projections.apps5_oidc_configs.id_token_userinfo_assertion,` +
|
||||
` projections.apps5_oidc_configs.clock_skew,` +
|
||||
` projections.apps5_oidc_configs.additional_origins,` +
|
||||
` projections.apps5_oidc_configs.skip_native_app_success_page,` +
|
||||
//saml config
|
||||
` projections.apps4_saml_configs.app_id,` +
|
||||
` projections.apps4_saml_configs.entity_id,` +
|
||||
` projections.apps4_saml_configs.metadata,` +
|
||||
` projections.apps4_saml_configs.metadata_url` +
|
||||
` FROM projections.apps4` +
|
||||
` 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.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.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id` +
|
||||
` projections.apps5_saml_configs.app_id,` +
|
||||
` projections.apps5_saml_configs.entity_id,` +
|
||||
` projections.apps5_saml_configs.metadata,` +
|
||||
` projections.apps5_saml_configs.metadata_url` +
|
||||
` FROM projections.apps5` +
|
||||
` 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.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.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'`)
|
||||
expectedAppsQuery = regexp.QuoteMeta(`SELECT projections.apps4.id,` +
|
||||
` projections.apps4.name,` +
|
||||
` projections.apps4.project_id,` +
|
||||
` projections.apps4.creation_date,` +
|
||||
` projections.apps4.change_date,` +
|
||||
` projections.apps4.resource_owner,` +
|
||||
` projections.apps4.state,` +
|
||||
` projections.apps4.sequence,` +
|
||||
expectedAppsQuery = regexp.QuoteMeta(`SELECT projections.apps5.id,` +
|
||||
` projections.apps5.name,` +
|
||||
` projections.apps5.project_id,` +
|
||||
` projections.apps5.creation_date,` +
|
||||
` projections.apps5.change_date,` +
|
||||
` projections.apps5.resource_owner,` +
|
||||
` projections.apps5.state,` +
|
||||
` projections.apps5.sequence,` +
|
||||
// api config
|
||||
` projections.apps4_api_configs.app_id,` +
|
||||
` projections.apps4_api_configs.client_id,` +
|
||||
` projections.apps4_api_configs.auth_method,` +
|
||||
` projections.apps5_api_configs.app_id,` +
|
||||
` projections.apps5_api_configs.client_id,` +
|
||||
` projections.apps5_api_configs.auth_method,` +
|
||||
// oidc config
|
||||
` projections.apps4_oidc_configs.app_id,` +
|
||||
` projections.apps4_oidc_configs.version,` +
|
||||
` projections.apps4_oidc_configs.client_id,` +
|
||||
` projections.apps4_oidc_configs.redirect_uris,` +
|
||||
` projections.apps4_oidc_configs.response_types,` +
|
||||
` projections.apps4_oidc_configs.grant_types,` +
|
||||
` projections.apps4_oidc_configs.application_type,` +
|
||||
` projections.apps4_oidc_configs.auth_method_type,` +
|
||||
` projections.apps4_oidc_configs.post_logout_redirect_uris,` +
|
||||
` projections.apps4_oidc_configs.is_dev_mode,` +
|
||||
` projections.apps4_oidc_configs.access_token_type,` +
|
||||
` projections.apps4_oidc_configs.access_token_role_assertion,` +
|
||||
` projections.apps4_oidc_configs.id_token_role_assertion,` +
|
||||
` projections.apps4_oidc_configs.id_token_userinfo_assertion,` +
|
||||
` projections.apps4_oidc_configs.clock_skew,` +
|
||||
` projections.apps4_oidc_configs.additional_origins,` +
|
||||
` projections.apps5_oidc_configs.app_id,` +
|
||||
` projections.apps5_oidc_configs.version,` +
|
||||
` projections.apps5_oidc_configs.client_id,` +
|
||||
` projections.apps5_oidc_configs.redirect_uris,` +
|
||||
` projections.apps5_oidc_configs.response_types,` +
|
||||
` projections.apps5_oidc_configs.grant_types,` +
|
||||
` projections.apps5_oidc_configs.application_type,` +
|
||||
` projections.apps5_oidc_configs.auth_method_type,` +
|
||||
` projections.apps5_oidc_configs.post_logout_redirect_uris,` +
|
||||
` projections.apps5_oidc_configs.is_dev_mode,` +
|
||||
` projections.apps5_oidc_configs.access_token_type,` +
|
||||
` projections.apps5_oidc_configs.access_token_role_assertion,` +
|
||||
` projections.apps5_oidc_configs.id_token_role_assertion,` +
|
||||
` projections.apps5_oidc_configs.id_token_userinfo_assertion,` +
|
||||
` projections.apps5_oidc_configs.clock_skew,` +
|
||||
` projections.apps5_oidc_configs.additional_origins,` +
|
||||
` projections.apps5_oidc_configs.skip_native_app_success_page,` +
|
||||
//saml config
|
||||
` projections.apps4_saml_configs.app_id,` +
|
||||
` projections.apps4_saml_configs.entity_id,` +
|
||||
` projections.apps4_saml_configs.metadata,` +
|
||||
` projections.apps4_saml_configs.metadata_url,` +
|
||||
` projections.apps5_saml_configs.app_id,` +
|
||||
` projections.apps5_saml_configs.entity_id,` +
|
||||
` projections.apps5_saml_configs.metadata,` +
|
||||
` projections.apps5_saml_configs.metadata_url,` +
|
||||
` COUNT(*) OVER ()` +
|
||||
` FROM projections.apps4` +
|
||||
` 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.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.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id` +
|
||||
` FROM projections.apps5` +
|
||||
` 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.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.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'`)
|
||||
expectedAppIDsQuery = regexp.QuoteMeta(`SELECT projections.apps4_api_configs.client_id,` +
|
||||
` projections.apps4_oidc_configs.client_id` +
|
||||
` FROM projections.apps4` +
|
||||
` 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.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
|
||||
expectedAppIDsQuery = regexp.QuoteMeta(`SELECT projections.apps5_api_configs.client_id,` +
|
||||
` projections.apps5_oidc_configs.client_id` +
|
||||
` FROM projections.apps5` +
|
||||
` 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.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'`)
|
||||
expectedProjectIDByAppQuery = regexp.QuoteMeta(`SELECT projections.apps4.project_id` +
|
||||
` FROM projections.apps4` +
|
||||
` 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.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.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id` +
|
||||
expectedProjectIDByAppQuery = regexp.QuoteMeta(`SELECT projections.apps5.project_id` +
|
||||
` FROM projections.apps5` +
|
||||
` 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.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.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'`)
|
||||
expectedProjectByAppQuery = regexp.QuoteMeta(`SELECT projections.projects3.id,` +
|
||||
` projections.projects3.creation_date,` +
|
||||
@ -118,10 +120,10 @@ var (
|
||||
` projections.projects3.has_project_check,` +
|
||||
` projections.projects3.private_labeling_setting` +
|
||||
` FROM projections.projects3` +
|
||||
` JOIN projections.apps4 ON projections.projects3.id = projections.apps4.project_id AND projections.projects3.instance_id = projections.apps4.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.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.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.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.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.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.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'`)
|
||||
|
||||
appCols = database.StringArray{
|
||||
@ -154,6 +156,7 @@ var (
|
||||
"id_token_userinfo_assertion",
|
||||
"clock_skew",
|
||||
"additional_origins",
|
||||
"skip_native_app_success_page",
|
||||
//saml config
|
||||
"app_id",
|
||||
"entity_id",
|
||||
@ -224,6 +227,7 @@ func Test_AppsPrepare(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
// saml config
|
||||
nil,
|
||||
nil,
|
||||
@ -289,6 +293,7 @@ func Test_AppsPrepare(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
// saml config
|
||||
nil,
|
||||
nil,
|
||||
@ -357,6 +362,7 @@ func Test_AppsPrepare(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
// saml config
|
||||
"app-id",
|
||||
"https://test.com/saml/metadata",
|
||||
@ -427,6 +433,7 @@ func Test_AppsPrepare(t *testing.T) {
|
||||
true,
|
||||
1 * time.Second,
|
||||
database.StringArray{"additional.origin"},
|
||||
false,
|
||||
// saml config
|
||||
nil,
|
||||
nil,
|
||||
@ -451,23 +458,24 @@ func Test_AppsPrepare(t *testing.T) {
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: true,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: true,
|
||||
AssertIDTokenRole: true,
|
||||
AssertIDTokenUserinfo: true,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: true,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: true,
|
||||
AssertIDTokenRole: true,
|
||||
AssertIDTokenUserinfo: true,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||
SkipNativeAppSuccessPage: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -511,6 +519,7 @@ func Test_AppsPrepare(t *testing.T) {
|
||||
true,
|
||||
1 * time.Second,
|
||||
database.StringArray{"additional.origin"},
|
||||
false,
|
||||
// saml config
|
||||
nil,
|
||||
nil,
|
||||
@ -535,23 +544,24 @@ func Test_AppsPrepare(t *testing.T) {
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
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"},
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
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: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -595,6 +605,7 @@ func Test_AppsPrepare(t *testing.T) {
|
||||
true,
|
||||
1 * time.Second,
|
||||
database.StringArray{"additional.origin"},
|
||||
false,
|
||||
// saml config
|
||||
nil,
|
||||
nil,
|
||||
@ -619,23 +630,24 @@ func Test_AppsPrepare(t *testing.T) {
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: true,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: true,
|
||||
AssertIDTokenRole: false,
|
||||
AssertIDTokenUserinfo: true,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: true,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: true,
|
||||
AssertIDTokenRole: false,
|
||||
AssertIDTokenUserinfo: true,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||
SkipNativeAppSuccessPage: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -679,6 +691,7 @@ func Test_AppsPrepare(t *testing.T) {
|
||||
true,
|
||||
1 * time.Second,
|
||||
database.StringArray{"additional.origin"},
|
||||
false,
|
||||
// saml config
|
||||
nil,
|
||||
nil,
|
||||
@ -703,23 +716,24 @@ func Test_AppsPrepare(t *testing.T) {
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: false,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: false,
|
||||
AssertIDTokenRole: true,
|
||||
AssertIDTokenUserinfo: true,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: false,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: false,
|
||||
AssertIDTokenRole: true,
|
||||
AssertIDTokenUserinfo: true,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||
SkipNativeAppSuccessPage: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -763,6 +777,7 @@ func Test_AppsPrepare(t *testing.T) {
|
||||
true,
|
||||
1 * time.Second,
|
||||
database.StringArray{"additional.origin"},
|
||||
false,
|
||||
// saml config
|
||||
nil,
|
||||
nil,
|
||||
@ -787,23 +802,110 @@ func Test_AppsPrepare(t *testing.T) {
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: false,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: true,
|
||||
AssertIDTokenRole: true,
|
||||
AssertIDTokenUserinfo: true,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: false,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: true,
|
||||
AssertIDTokenRole: true,
|
||||
AssertIDTokenUserinfo: true,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
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,
|
||||
1 * time.Second,
|
||||
database.StringArray{"additional.origin"},
|
||||
false,
|
||||
// saml config
|
||||
nil,
|
||||
nil,
|
||||
@ -883,6 +986,7 @@ func Test_AppsPrepare(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
// saml config
|
||||
nil,
|
||||
nil,
|
||||
@ -919,6 +1023,7 @@ func Test_AppsPrepare(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
// saml config
|
||||
"saml-app-id",
|
||||
"https://test.com/saml/metadata",
|
||||
@ -943,23 +1048,24 @@ func Test_AppsPrepare(t *testing.T) {
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: true,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: true,
|
||||
AssertIDTokenRole: true,
|
||||
AssertIDTokenUserinfo: true,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: true,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: true,
|
||||
AssertIDTokenRole: true,
|
||||
AssertIDTokenUserinfo: true,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||
SkipNativeAppSuccessPage: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -1085,6 +1191,7 @@ func Test_AppPrepare(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
// saml config
|
||||
nil,
|
||||
nil,
|
||||
@ -1142,6 +1249,7 @@ func Test_AppPrepare(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
// saml config
|
||||
nil,
|
||||
nil,
|
||||
@ -1204,6 +1312,7 @@ func Test_AppPrepare(t *testing.T) {
|
||||
true,
|
||||
1 * time.Second,
|
||||
database.StringArray{"additional.origin"},
|
||||
false,
|
||||
// saml config
|
||||
nil,
|
||||
nil,
|
||||
@ -1223,23 +1332,24 @@ func Test_AppPrepare(t *testing.T) {
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: true,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: true,
|
||||
AssertIDTokenRole: true,
|
||||
AssertIDTokenUserinfo: true,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: true,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: true,
|
||||
AssertIDTokenRole: true,
|
||||
AssertIDTokenUserinfo: true,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||
SkipNativeAppSuccessPage: false,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
@ -1280,6 +1390,7 @@ func Test_AppPrepare(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
// saml config
|
||||
"app-id",
|
||||
"https://test.com/saml/metadata",
|
||||
@ -1343,6 +1454,7 @@ func Test_AppPrepare(t *testing.T) {
|
||||
true,
|
||||
1 * time.Second,
|
||||
database.StringArray{"additional.origin"},
|
||||
false,
|
||||
// saml config
|
||||
nil,
|
||||
nil,
|
||||
@ -1362,23 +1474,24 @@ func Test_AppPrepare(t *testing.T) {
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: false,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: true,
|
||||
AssertIDTokenRole: true,
|
||||
AssertIDTokenUserinfo: true,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: false,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: true,
|
||||
AssertIDTokenRole: true,
|
||||
AssertIDTokenUserinfo: true,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||
SkipNativeAppSuccessPage: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -1420,6 +1533,7 @@ func Test_AppPrepare(t *testing.T) {
|
||||
true,
|
||||
1 * time.Second,
|
||||
database.StringArray{"additional.origin"},
|
||||
false,
|
||||
// saml config
|
||||
nil,
|
||||
nil,
|
||||
@ -1439,23 +1553,24 @@ func Test_AppPrepare(t *testing.T) {
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: true,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: false,
|
||||
AssertIDTokenRole: true,
|
||||
AssertIDTokenUserinfo: true,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: true,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: false,
|
||||
AssertIDTokenRole: true,
|
||||
AssertIDTokenUserinfo: true,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||
SkipNativeAppSuccessPage: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -1497,6 +1612,7 @@ func Test_AppPrepare(t *testing.T) {
|
||||
true,
|
||||
1 * time.Second,
|
||||
database.StringArray{"additional.origin"},
|
||||
false,
|
||||
// saml config
|
||||
nil,
|
||||
nil,
|
||||
@ -1516,23 +1632,24 @@ func Test_AppPrepare(t *testing.T) {
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: true,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: true,
|
||||
AssertIDTokenRole: false,
|
||||
AssertIDTokenUserinfo: true,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: true,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: true,
|
||||
AssertIDTokenRole: false,
|
||||
AssertIDTokenUserinfo: true,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||
SkipNativeAppSuccessPage: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -1574,6 +1691,7 @@ func Test_AppPrepare(t *testing.T) {
|
||||
false,
|
||||
1 * time.Second,
|
||||
database.StringArray{"additional.origin"},
|
||||
false,
|
||||
// saml config
|
||||
nil,
|
||||
nil,
|
||||
@ -1593,23 +1711,24 @@ func Test_AppPrepare(t *testing.T) {
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: true,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: true,
|
||||
AssertIDTokenRole: true,
|
||||
AssertIDTokenUserinfo: false,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||
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.OIDCApplicationTypeUserAgent,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"},
|
||||
IsDevMode: true,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AssertAccessTokenRole: true,
|
||||
AssertIDTokenRole: true,
|
||||
AssertIDTokenUserinfo: false,
|
||||
ClockSkew: 1 * time.Second,
|
||||
AdditionalOrigins: database.StringArray{"additional.origin"},
|
||||
ComplianceProblems: nil,
|
||||
AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"},
|
||||
SkipNativeAppSuccessPage: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -15,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
AppProjectionTable = "projections.apps4"
|
||||
AppProjectionTable = "projections.apps5"
|
||||
AppAPITable = AppProjectionTable + "_" + appAPITableSuffix
|
||||
AppOIDCTable = AppProjectionTable + "_" + appOIDCTableSuffix
|
||||
AppSAMLTable = AppProjectionTable + "_" + appSAMLTableSuffix
|
||||
@ -57,6 +57,7 @@ const (
|
||||
AppOIDCConfigColumnIDTokenUserinfoAssertion = "id_token_userinfo_assertion"
|
||||
AppOIDCConfigColumnClockSkew = "clock_skew"
|
||||
AppOIDCConfigColumnAdditionalOrigins = "additional_origins"
|
||||
AppOIDCConfigColumnSkipNativeAppSuccessPage = "skip_native_app_success_page"
|
||||
|
||||
appSAMLTableSuffix = "saml_configs"
|
||||
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(AppOIDCConfigColumnClockSkew, crdb.ColumnTypeInt64, crdb.Default(0)),
|
||||
crdb.NewColumn(AppOIDCConfigColumnAdditionalOrigins, crdb.ColumnTypeTextArray, crdb.Nullable()),
|
||||
crdb.NewColumn(AppOIDCConfigColumnSkipNativeAppSuccessPage, crdb.ColumnTypeBool, crdb.Default(false)),
|
||||
},
|
||||
crdb.NewPrimaryKey(AppOIDCConfigColumnInstanceID, AppOIDCConfigColumnAppID),
|
||||
appOIDCTableSuffix,
|
||||
@ -463,6 +465,7 @@ func (p *appProjection) reduceOIDCConfigAdded(event eventstore.Event) (*handler.
|
||||
handler.NewCol(AppOIDCConfigColumnIDTokenUserinfoAssertion, e.IDTokenUserinfoAssertion),
|
||||
handler.NewCol(AppOIDCConfigColumnClockSkew, e.ClockSkew),
|
||||
handler.NewCol(AppOIDCConfigColumnAdditionalOrigins, database.StringArray(e.AdditionalOrigins)),
|
||||
handler.NewCol(AppOIDCConfigColumnSkipNativeAppSuccessPage, e.SkipNativeAppSuccessPage),
|
||||
},
|
||||
crdb.WithTableSuffix(appOIDCTableSuffix),
|
||||
),
|
||||
@ -528,6 +531,9 @@ func (p *appProjection) reduceOIDCConfigChanged(event eventstore.Event) (*handle
|
||||
if e.AdditionalOrigins != nil {
|
||||
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 {
|
||||
return crdb.NewNoOpStatement(e), nil
|
||||
|
@ -45,7 +45,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
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{}{
|
||||
"app-id",
|
||||
"my-app",
|
||||
@ -82,7 +82,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
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{}{
|
||||
"my-app",
|
||||
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",
|
||||
args: args{
|
||||
@ -114,7 +135,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
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{}{
|
||||
domain.AppStateInactive,
|
||||
anyArg{},
|
||||
@ -146,7 +167,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
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{}{
|
||||
domain.AppStateActive,
|
||||
anyArg{},
|
||||
@ -178,7 +199,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
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{}{
|
||||
"app-id",
|
||||
"instance-id",
|
||||
@ -205,7 +226,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
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{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@ -232,7 +253,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "DELETE FROM projections.apps4 WHERE (instance_id = $1)",
|
||||
expectedStmt: "DELETE FROM projections.apps5 WHERE (instance_id = $1)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
},
|
||||
@ -263,7 +284,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
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{}{
|
||||
"app-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{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@ -307,7 +328,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
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{}{
|
||||
anyArg{},
|
||||
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{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@ -369,7 +390,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
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{}{
|
||||
anyArg{},
|
||||
"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{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@ -412,7 +433,8 @@ func TestAppProjection_reduces(t *testing.T) {
|
||||
"idTokenRoleAssertion": true,
|
||||
"idTokenUserinfoAssertion": true,
|
||||
"clockSkew": 1000,
|
||||
"additionalOrigins": ["origin.one.ch", "origin.two.ch"]
|
||||
"additionalOrigins": ["origin.one.ch", "origin.two.ch"],
|
||||
"skipNativeAppSuccessPage": true
|
||||
}`),
|
||||
), project.OIDCConfigAddedEventMapper),
|
||||
},
|
||||
@ -424,7 +446,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
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{}{
|
||||
"app-id",
|
||||
"instance-id",
|
||||
@ -444,10 +466,11 @@ func TestAppProjection_reduces(t *testing.T) {
|
||||
true,
|
||||
1 * time.Microsecond,
|
||||
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{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@ -480,7 +503,9 @@ func TestAppProjection_reduces(t *testing.T) {
|
||||
"idTokenRoleAssertion": true,
|
||||
"idTokenUserinfoAssertion": true,
|
||||
"clockSkew": 1000,
|
||||
"additionalOrigins": ["origin.one.ch", "origin.two.ch"]
|
||||
"additionalOrigins": ["origin.one.ch", "origin.two.ch"],
|
||||
"skipNativeAppSuccessPage": true
|
||||
|
||||
}`),
|
||||
), project.OIDCConfigChangedEventMapper),
|
||||
},
|
||||
@ -492,7 +517,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
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{}{
|
||||
domain.OIDCVersionV1,
|
||||
database.StringArray{"redirect.one.ch", "redirect.two.ch"},
|
||||
@ -508,12 +533,13 @@ func TestAppProjection_reduces(t *testing.T) {
|
||||
true,
|
||||
1 * time.Microsecond,
|
||||
database.StringArray{"origin.one.ch", "origin.two.ch"},
|
||||
true,
|
||||
"app-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{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@ -566,7 +592,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
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{}{
|
||||
anyArg{},
|
||||
"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{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@ -603,7 +629,7 @@ func TestAppProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
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{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
|
@ -40,6 +40,7 @@ type OIDCConfigAddedEvent struct {
|
||||
IDTokenUserinfoAssertion bool `json:"idTokenUserinfoAssertion,omitempty"`
|
||||
ClockSkew time.Duration `json:"clockSkew,omitempty"`
|
||||
AdditionalOrigins []string `json:"additionalOrigins,omitempty"`
|
||||
SkipNativeAppSuccessPage bool `json:"skipNativeAppSuccessPage,omitempty"`
|
||||
}
|
||||
|
||||
func (e *OIDCConfigAddedEvent) Data() interface{} {
|
||||
@ -70,6 +71,7 @@ func NewOIDCConfigAddedEvent(
|
||||
idTokenUserinfoAssertion bool,
|
||||
clockSkew time.Duration,
|
||||
additionalOrigins []string,
|
||||
skipNativeAppSuccessPage bool,
|
||||
) *OIDCConfigAddedEvent {
|
||||
return &OIDCConfigAddedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
@ -94,6 +96,7 @@ func NewOIDCConfigAddedEvent(
|
||||
IDTokenUserinfoAssertion: idTokenUserinfoAssertion,
|
||||
ClockSkew: clockSkew,
|
||||
AdditionalOrigins: additionalOrigins,
|
||||
SkipNativeAppSuccessPage: skipNativeAppSuccessPage,
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,8 +182,7 @@ func (e *OIDCConfigAddedEvent) Validate(cmd eventstore.Command) bool {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
return e.SkipNativeAppSuccessPage == c.SkipNativeAppSuccessPage
|
||||
}
|
||||
|
||||
func OIDCConfigAddedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||
@ -214,6 +216,7 @@ type OIDCConfigChangedEvent struct {
|
||||
IDTokenUserinfoAssertion *bool `json:"idTokenUserinfoAssertion,omitempty"`
|
||||
ClockSkew *time.Duration `json:"clockSkew,omitempty"`
|
||||
AdditionalOrigins *[]string `json:"additionalOrigins,omitempty"`
|
||||
SkipNativeAppSuccessPage *bool `json:"skipNativeAppSuccessPage,omitempty"`
|
||||
}
|
||||
|
||||
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) {
|
||||
e := &OIDCConfigChangedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
|
@ -163,6 +163,11 @@ message OIDCConfig {
|
||||
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 {
|
||||
|
@ -8773,6 +8773,11 @@ message AddOIDCAppRequest {
|
||||
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 {
|
||||
@ -8943,6 +8948,11 @@ message UpdateOIDCAppConfigRequest {
|
||||
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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user