mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 00:27:31 +00:00
feat: add apple as idp (#6442)
* feat: manage apple idp * handle apple idp callback * add tests for provider * basic console implementation * implement flow for login UI and add logos / styling * tests * cleanup * add upload button * begin i18n * apple logo positioning, file upload component * fix add apple instance idp * add missing apple logos for login * update to go 1.21 * fix slice compare * revert permission changes * concrete error messages * translate login apple logo -y-2px * change form parsing * sign in button * fix tests * lint console --------- Co-authored-by: peintnermax <max@caos.ch>
This commit is contained in:
@@ -3,9 +3,8 @@ package login
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
|
||||
http_mw "github.com/zitadel/zitadel/internal/api/http/middleware"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
"github.com/zitadel/zitadel/internal/idp"
|
||||
"github.com/zitadel/zitadel/internal/idp/providers/apple"
|
||||
"github.com/zitadel/zitadel/internal/idp/providers/azuread"
|
||||
"github.com/zitadel/zitadel/internal/idp/providers/github"
|
||||
"github.com/zitadel/zitadel/internal/idp/providers/gitlab"
|
||||
@@ -41,6 +42,9 @@ type externalIDPData struct {
|
||||
type externalIDPCallbackData struct {
|
||||
State string `schema:"state"`
|
||||
Code string `schema:"code"`
|
||||
|
||||
// Apple returns a user on first registration
|
||||
User string `schema:"user"`
|
||||
}
|
||||
|
||||
type externalNotFoundOptionFormData struct {
|
||||
@@ -159,6 +163,8 @@ func (l *Login) handleIDP(w http.ResponseWriter, r *http.Request, authReq *domai
|
||||
provider, err = l.gitlabSelfHostedProvider(r.Context(), identityProvider)
|
||||
case domain.IDPTypeGoogle:
|
||||
provider, err = l.googleProvider(r.Context(), identityProvider)
|
||||
case domain.IDPTypeApple:
|
||||
provider, err = l.appleProvider(r.Context(), identityProvider)
|
||||
case domain.IDPTypeLDAP:
|
||||
provider, err = l.ldapProvider(r.Context(), identityProvider)
|
||||
case domain.IDPTypeUnspecified:
|
||||
@@ -180,6 +186,18 @@ func (l *Login) handleIDP(w http.ResponseWriter, r *http.Request, authReq *domai
|
||||
http.Redirect(w, r, session.GetAuthURL(), http.StatusFound)
|
||||
}
|
||||
|
||||
// handleExternalLoginCallbackForm handles the callback from a IDP with form_post.
|
||||
// It will redirect to the "normal" callback endpoint with the form data as query parameter.
|
||||
// This way cookies will be handled correctly (same site = lax).
|
||||
func (l *Login) handleExternalLoginCallbackForm(w http.ResponseWriter, r *http.Request) {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
l.renderLogin(w, r, nil, err)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, HandlerPrefix+EndpointExternalLoginCallback+"?"+r.Form.Encode(), 302)
|
||||
}
|
||||
|
||||
// handleExternalLoginCallback handles the callback from a IDP
|
||||
// and tries to extract the user with the provided data
|
||||
func (l *Login) handleExternalLoginCallback(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -259,6 +277,13 @@ func (l *Login) handleExternalLoginCallback(w http.ResponseWriter, r *http.Reque
|
||||
return
|
||||
}
|
||||
session = &openid.Session{Provider: provider.(*google.Provider).Provider, Code: data.Code}
|
||||
case domain.IDPTypeApple:
|
||||
provider, err = l.appleProvider(r.Context(), identityProvider)
|
||||
if err != nil {
|
||||
l.externalAuthFailed(w, r, authReq, nil, nil, err)
|
||||
return
|
||||
}
|
||||
session = &apple.Session{Session: &openid.Session{Provider: provider.(*apple.Provider).Provider, Code: data.Code}, UserFormValue: data.User}
|
||||
case domain.IDPTypeJWT,
|
||||
domain.IDPTypeLDAP,
|
||||
domain.IDPTypeUnspecified:
|
||||
@@ -936,6 +961,21 @@ func (l *Login) gitlabSelfHostedProvider(ctx context.Context, identityProvider *
|
||||
)
|
||||
}
|
||||
|
||||
func (l *Login) appleProvider(ctx context.Context, identityProvider *query.IDPTemplate) (*apple.Provider, error) {
|
||||
privateKey, err := crypto.Decrypt(identityProvider.AppleIDPTemplate.PrivateKey, l.idpConfigAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return apple.New(
|
||||
identityProvider.AppleIDPTemplate.ClientID,
|
||||
identityProvider.AppleIDPTemplate.TeamID,
|
||||
identityProvider.AppleIDPTemplate.KeyID,
|
||||
l.baseURL(ctx)+EndpointExternalLoginCallbackFormPost,
|
||||
privateKey,
|
||||
identityProvider.AppleIDPTemplate.Scopes,
|
||||
)
|
||||
}
|
||||
|
||||
func (l *Login) appendUserGrants(ctx context.Context, userGrants []*domain.UserGrant, resourceOwner string) error {
|
||||
if len(userGrants) == 0 {
|
||||
return nil
|
||||
@@ -971,6 +1011,8 @@ func tokens(session idp.Session) *oidc.Tokens[*oidc.IDTokenClaims] {
|
||||
return s.Tokens
|
||||
case *azuread.Session:
|
||||
return s.Tokens
|
||||
case *apple.Session:
|
||||
return s.Tokens
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@@ -120,6 +120,12 @@ func createCSRFInterceptor(cookieName string, csrfCookieKey []byte, externalSecu
|
||||
handler.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
// ignore form post callback
|
||||
// it will redirect to the "normal" callback, where the cookie is set again
|
||||
if r.URL.Path == EndpointExternalLoginCallbackFormPost && r.Method == http.MethodPost {
|
||||
handler.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
csrf.Protect(csrfCookieKey,
|
||||
csrf.Secure(externalSecure),
|
||||
csrf.CookieName(http_utils.SetCookiePrefix(cookieName, "", path, externalSecure)),
|
||||
|
@@ -7,44 +7,45 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
EndpointRoot = "/"
|
||||
EndpointHealthz = "/healthz"
|
||||
EndpointReadiness = "/ready"
|
||||
EndpointLogin = "/login"
|
||||
EndpointExternalLogin = "/login/externalidp"
|
||||
EndpointExternalLoginCallback = "/login/externalidp/callback"
|
||||
EndpointJWTAuthorize = "/login/jwt/authorize"
|
||||
EndpointJWTCallback = "/login/jwt/callback"
|
||||
EndpointLDAPLogin = "/login/ldap"
|
||||
EndpointLDAPCallback = "/login/ldap/callback"
|
||||
EndpointPasswordlessLogin = "/login/passwordless"
|
||||
EndpointPasswordlessRegistration = "/login/passwordless/init"
|
||||
EndpointPasswordlessPrompt = "/login/passwordless/prompt"
|
||||
EndpointLoginName = "/loginname"
|
||||
EndpointUserSelection = "/userselection"
|
||||
EndpointChangeUsername = "/username/change"
|
||||
EndpointPassword = "/password"
|
||||
EndpointInitPassword = "/password/init"
|
||||
EndpointChangePassword = "/password/change"
|
||||
EndpointPasswordReset = "/password/reset"
|
||||
EndpointInitUser = "/user/init"
|
||||
EndpointMFAVerify = "/mfa/verify"
|
||||
EndpointMFAPrompt = "/mfa/prompt"
|
||||
EndpointMFAInitVerify = "/mfa/init/verify"
|
||||
EndpointMFASMSInitVerify = "/mfa/init/sms/verify"
|
||||
EndpointMFAOTPVerify = "/mfa/otp/verify"
|
||||
EndpointMFAInitU2FVerify = "/mfa/init/u2f/verify"
|
||||
EndpointU2FVerification = "/mfa/u2f/verify"
|
||||
EndpointMailVerification = "/mail/verification"
|
||||
EndpointMailVerified = "/mail/verified"
|
||||
EndpointRegisterOption = "/register/option"
|
||||
EndpointRegister = "/register"
|
||||
EndpointExternalRegister = "/register/externalidp"
|
||||
EndpointExternalRegisterCallback = "/register/externalidp/callback"
|
||||
EndpointRegisterOrg = "/register/org"
|
||||
EndpointLogoutDone = "/logout/done"
|
||||
EndpointLoginSuccess = "/login/success"
|
||||
EndpointExternalNotFoundOption = "/externaluser/option"
|
||||
EndpointRoot = "/"
|
||||
EndpointHealthz = "/healthz"
|
||||
EndpointReadiness = "/ready"
|
||||
EndpointLogin = "/login"
|
||||
EndpointExternalLogin = "/login/externalidp"
|
||||
EndpointExternalLoginCallback = "/login/externalidp/callback"
|
||||
EndpointExternalLoginCallbackFormPost = "/login/externalidp/callback/form"
|
||||
EndpointJWTAuthorize = "/login/jwt/authorize"
|
||||
EndpointJWTCallback = "/login/jwt/callback"
|
||||
EndpointLDAPLogin = "/login/ldap"
|
||||
EndpointLDAPCallback = "/login/ldap/callback"
|
||||
EndpointPasswordlessLogin = "/login/passwordless"
|
||||
EndpointPasswordlessRegistration = "/login/passwordless/init"
|
||||
EndpointPasswordlessPrompt = "/login/passwordless/prompt"
|
||||
EndpointLoginName = "/loginname"
|
||||
EndpointUserSelection = "/userselection"
|
||||
EndpointChangeUsername = "/username/change"
|
||||
EndpointPassword = "/password"
|
||||
EndpointInitPassword = "/password/init"
|
||||
EndpointChangePassword = "/password/change"
|
||||
EndpointPasswordReset = "/password/reset"
|
||||
EndpointInitUser = "/user/init"
|
||||
EndpointMFAVerify = "/mfa/verify"
|
||||
EndpointMFAPrompt = "/mfa/prompt"
|
||||
EndpointMFAInitVerify = "/mfa/init/verify"
|
||||
EndpointMFASMSInitVerify = "/mfa/init/sms/verify"
|
||||
EndpointMFAOTPVerify = "/mfa/otp/verify"
|
||||
EndpointMFAInitU2FVerify = "/mfa/init/u2f/verify"
|
||||
EndpointU2FVerification = "/mfa/u2f/verify"
|
||||
EndpointMailVerification = "/mail/verification"
|
||||
EndpointMailVerified = "/mail/verified"
|
||||
EndpointRegisterOption = "/register/option"
|
||||
EndpointRegister = "/register"
|
||||
EndpointExternalRegister = "/register/externalidp"
|
||||
EndpointExternalRegisterCallback = "/register/externalidp/callback"
|
||||
EndpointRegisterOrg = "/register/org"
|
||||
EndpointLogoutDone = "/logout/done"
|
||||
EndpointLoginSuccess = "/login/success"
|
||||
EndpointExternalNotFoundOption = "/externaluser/option"
|
||||
|
||||
EndpointResources = "/resources"
|
||||
EndpointDynamicResources = "/resources/dynamic"
|
||||
@@ -71,6 +72,7 @@ func CreateRouter(login *Login, staticDir http.FileSystem, interceptors ...mux.M
|
||||
router.HandleFunc(EndpointLogin, login.handleLogin).Methods(http.MethodGet, http.MethodPost)
|
||||
router.HandleFunc(EndpointExternalLogin, login.handleExternalLogin).Methods(http.MethodGet)
|
||||
router.HandleFunc(EndpointExternalLoginCallback, login.handleExternalLoginCallback).Methods(http.MethodGet)
|
||||
router.HandleFunc(EndpointExternalLoginCallbackFormPost, login.handleExternalLoginCallbackForm).Methods(http.MethodPost)
|
||||
router.HandleFunc(EndpointJWTAuthorize, login.handleJWTRequest).Methods(http.MethodGet)
|
||||
router.HandleFunc(EndpointJWTCallback, login.handleJWTCallback).Methods(http.MethodGet)
|
||||
router.HandleFunc(EndpointPasswordlessLogin, login.handlePasswordlessVerification).Methods(http.MethodPost)
|
||||
|
@@ -360,6 +360,7 @@ Footer:
|
||||
PrivacyPolicy: Политика за поверителност
|
||||
Help: Помогне
|
||||
SupportEmail: Поддръжка на имейл
|
||||
SignIn: Влезте с {{.Provider}}
|
||||
Errors:
|
||||
Internal: Възникна вътрешна грешка
|
||||
AuthRequest:
|
||||
|
@@ -372,6 +372,8 @@ Footer:
|
||||
Help: Hilfe
|
||||
SupportEmail: Support E-Mail
|
||||
|
||||
SignIn: Mit {{.Provider}} anmelden
|
||||
|
||||
Errors:
|
||||
Internal: Es ist ein interner Fehler aufgetreten
|
||||
AuthRequest:
|
||||
|
@@ -372,6 +372,8 @@ Footer:
|
||||
Help: Help
|
||||
SupportEmail: Support E-mail
|
||||
|
||||
SignIn: Sign in with {{.Provider}}
|
||||
|
||||
Errors:
|
||||
Internal: An internal error occurred
|
||||
AuthRequest:
|
||||
|
@@ -354,6 +354,8 @@ Footer:
|
||||
Help: Ayuda
|
||||
SupportEmail: Email de soporte
|
||||
|
||||
SignIn: Iniciar sesión con {{.Provider}}
|
||||
|
||||
Errors:
|
||||
Internal: Se produjo un error interno
|
||||
AuthRequest:
|
||||
|
@@ -372,6 +372,8 @@ Footer:
|
||||
Help: Aide
|
||||
SupportEmail: E-mail d'assistance
|
||||
|
||||
SignIn: Connexion avec {{.Provider}}
|
||||
|
||||
Errors:
|
||||
Internal: Une erreur interne s'est produite
|
||||
AuthRequest:
|
||||
|
@@ -372,6 +372,8 @@ Footer:
|
||||
Help: Aiuto
|
||||
SupportEmail: E-mail di supporto
|
||||
|
||||
SignIn: Accedi con {{.Provider}}
|
||||
|
||||
Errors:
|
||||
Internal: Si è verificato un errore interno
|
||||
AuthRequest:
|
||||
|
@@ -363,6 +363,8 @@ Footer:
|
||||
PrivacyPolicy: プライバシーポリシー
|
||||
Help: ヘルプ
|
||||
|
||||
SignIn: '{{.Provider}} でサインイン'
|
||||
|
||||
Errors:
|
||||
Internal: 内部でエラーが発生しました
|
||||
AuthRequest:
|
||||
|
@@ -372,6 +372,8 @@ Footer:
|
||||
Help: Помош
|
||||
SupportEmail: Е-пошта за поддршка
|
||||
|
||||
SignIn: Пријавете се со {{.Provider}}
|
||||
|
||||
Errors:
|
||||
Internal: Се појави внатрешна грешка
|
||||
AuthRequest:
|
||||
|
@@ -372,6 +372,8 @@ Footer:
|
||||
Help: Pomoc
|
||||
SupportEmail: E-mail wsparcia
|
||||
|
||||
SignIn: Zaloguj się, używając konta {{.Provider}}
|
||||
|
||||
Errors:
|
||||
Internal: Wewnętrzny błąd
|
||||
AuthRequest:
|
||||
|
@@ -366,6 +366,8 @@ Footer:
|
||||
Help: Ajuda
|
||||
SupportEmail: E-mail de suporte
|
||||
|
||||
SignIn: Iniciar sessão com a {{.Provider}}
|
||||
|
||||
Errors:
|
||||
Internal: Ocorreu um erro interno
|
||||
AuthRequest:
|
||||
|
@@ -372,6 +372,8 @@ Footer:
|
||||
Help: 帮助
|
||||
SupportEmail: 支持邮箱
|
||||
|
||||
SignIn: 通过 {{.Provider}} 登录
|
||||
|
||||
Errors:
|
||||
Internal: 发生了内部错误
|
||||
AuthRequest:
|
||||
|
10
internal/api/ui/login/static/resources/images/idp/apple-dark.svg
Executable file
10
internal/api/ui/login/static/resources/images/idp/apple-dark.svg
Executable file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="56px" height="56px" viewBox="18 15.5 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 61 (89581) - https://sketch.com -->
|
||||
<title>White Logo Square </title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<g id="White-Logo-Square-" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<rect id="Rectangle" fill="" x="6" y="6" width="44" height="44"></rect>
|
||||
<path d="M28.2226562,20.3846154 C29.0546875,20.3846154 30.0976562,19.8048315 30.71875,19.0317864 C31.28125,18.3312142 31.6914062,17.352829 31.6914062,16.3744437 C31.6914062,16.2415766 31.6796875,16.1087095 31.65625,16 C30.7304687,16.0362365 29.6171875,16.640178 28.9492187,17.4494596 C28.421875,18.06548 27.9414062,19.0317864 27.9414062,20.0222505 C27.9414062,20.1671964 27.9648438,20.3121424 27.9765625,20.3604577 C28.0351562,20.3725366 28.1289062,20.3846154 28.2226562,20.3846154 Z M25.2929688,35 C26.4296875,35 26.9335938,34.214876 28.3515625,34.214876 C29.7929688,34.214876 30.109375,34.9758423 31.375,34.9758423 C32.6171875,34.9758423 33.4492188,33.792117 34.234375,32.6325493 C35.1132812,31.3038779 35.4765625,29.9993643 35.5,29.9389701 C35.4179688,29.9148125 33.0390625,28.9122695 33.0390625,26.0979021 C33.0390625,23.6579784 34.9140625,22.5588048 35.0195312,22.474253 C33.7773438,20.6382708 31.890625,20.5899555 31.375,20.5899555 C29.9804688,20.5899555 28.84375,21.4596313 28.1289062,21.4596313 C27.3554688,21.4596313 26.3359375,20.6382708 25.1289062,20.6382708 C22.8320312,20.6382708 20.5,22.5950413 20.5,26.2911634 C20.5,28.5861411 21.3671875,31.013986 22.4335938,32.5842339 C23.3476562,33.9129053 24.1445312,35 25.2929688,35 Z" id="" fill="#FFFFFF" fill-rule="nonzero"></path>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
10
internal/api/ui/login/static/resources/images/idp/apple.svg
Executable file
10
internal/api/ui/login/static/resources/images/idp/apple.svg
Executable file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="56px" height="56px" viewBox="18 15.5 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 61 (89581) - https://sketch.com -->
|
||||
<title>Black Logo Square</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<g id="Black-Logo-Square" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<rect id="Rectangle" fill="" x="6" y="6" width="44" height="44"></rect>
|
||||
<path d="M28.2226562,20.3846154 C29.0546875,20.3846154 30.0976562,19.8048315 30.71875,19.0317864 C31.28125,18.3312142 31.6914062,17.352829 31.6914062,16.3744437 C31.6914062,16.2415766 31.6796875,16.1087095 31.65625,16 C30.7304687,16.0362365 29.6171875,16.640178 28.9492187,17.4494596 C28.421875,18.06548 27.9414062,19.0317864 27.9414062,20.0222505 C27.9414062,20.1671964 27.9648438,20.3121424 27.9765625,20.3604577 C28.0351562,20.3725366 28.1289062,20.3846154 28.2226562,20.3846154 Z M25.2929688,35 C26.4296875,35 26.9335938,34.214876 28.3515625,34.214876 C29.7929688,34.214876 30.109375,34.9758423 31.375,34.9758423 C32.6171875,34.9758423 33.4492188,33.792117 34.234375,32.6325493 C35.1132812,31.3038779 35.4765625,29.9993643 35.5,29.9389701 C35.4179688,29.9148125 33.0390625,28.9122695 33.0390625,26.0979021 C33.0390625,23.6579784 34.9140625,22.5588048 35.0195312,22.474253 C33.7773438,20.6382708 31.890625,20.5899555 31.375,20.5899555 C29.9804688,20.5899555 28.84375,21.4596313 28.1289062,21.4596313 C27.3554688,21.4596313 26.3359375,20.6382708 25.1289062,20.6382708 C22.8320312,20.6382708 20.5,22.5950413 20.5,26.2911634 C20.5,28.5861411 21.3671875,31.013986 22.4335938,32.5842339 C23.3476562,33.9129053 24.1445312,35 25.2929688,35 Z" id="" fill="#000000" fill-rule="nonzero"></path>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
@@ -2,6 +2,7 @@ $lgn-idp-margin: 0.5rem 0;
|
||||
$lgn-idp-padding: 0 1px;
|
||||
$lgn-idp-provider-name-line-height: 36px;
|
||||
$lgn-idp-border-radius: 0.5rem;
|
||||
$lgn-idp-logo-size: 46px;
|
||||
|
||||
@mixin lgn-idp-base {
|
||||
display: block;
|
||||
@@ -17,14 +18,14 @@ $lgn-idp-border-radius: 0.5rem;
|
||||
transition: border-color 0.2s ease-in-out;
|
||||
|
||||
span.logo {
|
||||
height: 46px;
|
||||
width: 46px;
|
||||
height: $lgn-idp-logo-size;
|
||||
width: $lgn-idp-logo-size;
|
||||
}
|
||||
|
||||
span.provider-name {
|
||||
line-height: $lgn-idp-provider-name-line-height;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
position: relative;
|
||||
left: calc(50% - $lgn-idp-logo-size);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
@@ -75,4 +76,17 @@ $lgn-idp-border-radius: 0.5rem;
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
&.apple {
|
||||
span.logo {
|
||||
height: 46px;
|
||||
width: 46px;
|
||||
background-image: var(--apple-image-src);
|
||||
background-size: 25px;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 5px;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -117,6 +117,8 @@
|
||||
--zitadel-color-github-background: #ffffff;
|
||||
--zitadel-color-gitlab-text: #8b8d8d;
|
||||
--zitadel-color-gitlab-background: #ffffff;
|
||||
--zitadel-color-apple-text: #8b8d8d;
|
||||
--zitadel-color-apple-background: #ffffff;
|
||||
|
||||
--zitadel-color-qr: var(--zitadel-color-black);
|
||||
--zitadel-color-qr-background: var(--zitadel-color-white);
|
||||
@@ -125,6 +127,7 @@
|
||||
--github-image-src: url(../../../images/idp/github.png);
|
||||
--gitlab-image-src: url(../../../images/idp/gitlab.png);
|
||||
--azure-image-src: url(../../../images/idp/ms.svg);
|
||||
--apple-image-src: url(../../../images/idp/apple.svg);
|
||||
}
|
||||
|
||||
.lgn-dark-theme {
|
||||
@@ -227,9 +230,12 @@
|
||||
--zitadel-color-github-background: #ffffff;
|
||||
--zitadel-color-gitlab-text: #8b8d8d;
|
||||
--zitadel-color-gitlab-background: #ffffff;
|
||||
--zitadel-color-apple-text: #8b8d8d;
|
||||
--zitadel-color-apple-background: #ffffff;
|
||||
|
||||
--google-image-src: url(../../../images/idp/google.png);
|
||||
--github-image-src: url(../../../images/idp/github-white.png);
|
||||
--gitlab-image-src: url(../../../images/idp/gitlab.png);
|
||||
--azure-image-src: url(../../../images/idp/ms.svg);
|
||||
--apple-image-src: url(../../../images/idp/apple-dark.svg);
|
||||
}
|
||||
|
@@ -52,7 +52,11 @@
|
||||
<a href="{{ externalIDPAuthURL $reqid $provider.IDPConfigID}}"
|
||||
class="lgn-idp {{idpProviderClass $provider.IDPType}}">
|
||||
<span class="logo"></span>
|
||||
{{if $provider.IDPType.IsSignInButton}}
|
||||
<span class="provider-name">{{t "SignIn" "Provider" $provider.DisplayName}}</span>
|
||||
{{else}}
|
||||
<span class="provider-name">{{$provider.DisplayName}}</span>
|
||||
{{end}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
|
@@ -29,7 +29,11 @@
|
||||
<a href="{{ externalIDPRegisterURL $reqid $provider.IDPConfigID}}"
|
||||
class="lgn-idp {{idpProviderClass $provider.IDPType}}">
|
||||
<span class="logo"></span>
|
||||
{{if $provider.IDPType.IsSignInButton}}
|
||||
<span class="provider-name">{{t "SignIn" "Provider" $provider.DisplayName}}</span>
|
||||
{{else}}
|
||||
<span class="provider-name">{{$provider.DisplayName}}</span>
|
||||
{{end}}
|
||||
</a>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
Reference in New Issue
Block a user