Skip to content

Commit

Permalink
Merge pull request #396 from MadAppGang/federated-oidc-settings
Browse files Browse the repository at this point in the history
federated OIDC settings
  • Loading branch information
hummerd authored Mar 10, 2023
2 parents 6078ec4 + d433b64 commit 447686f
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 24 deletions.
23 changes: 12 additions & 11 deletions localization/messages_const.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions localization/translations/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ error.federated.idtoken.missing: "No id_token returned for federated login"
error.federated.idtoken.invalid: "Invalid id_token returned for federated login: %v"
error.federated.claims.error: "Invalid claims error: %v"
error.federated.oidc.provider.error: "Failed to init OIDC provider: %v"
error.federated.oidc.disabled: "Federated OIDC login disabled"


# Storages
error.storage.update_user.error: "Unable to update user with id %s with error: %v"
Expand Down
1 change: 1 addition & 0 deletions model/oidc_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type OIDCSettings struct {
EmailClaimField string `bson:"email_claim_field,omitempty" json:"email_claim_field,omitempty"`
UserIDClaimField string `bson:"user_id_claim_field,omitempty" json:"user_id_claim_field,omitempty"`
Scopes []string `bson:"scopes,omitempty" json:"scopes,omitempty"`
InitURL string `bson:"init_url,omitempty" json:"init_url,omitempty"`
// ScopeMapping maps OIDC scopes to Identifo scopes.
ScopeMapping map[string]string `bson:"scope_mapping,omitempty" json:"scope_mapping,omitempty"`
}
Expand Down
9 changes: 5 additions & 4 deletions model/server_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,11 @@ type LoginSettings struct {

// LoginWith is a type for configuring supported login ways.
type LoginWith struct {
Username bool `yaml:"username" json:"username"`
Phone bool `yaml:"phone" json:"phone"`
Email bool `yaml:"email" json:"email"`
Federated bool `yaml:"federated" json:"federated"`
Username bool `yaml:"username" json:"username"`
Phone bool `yaml:"phone" json:"phone"`
Email bool `yaml:"email" json:"email"`
Federated bool `yaml:"federated" json:"federated"`
FederatedOIDC bool `yaml:"federatedOIDC" json:"federated_oidc"`
}

// TFAType is a type of two-factor authentication for apps that support it.
Expand Down
7 changes: 4 additions & 3 deletions model/server_settings_defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ var DefaultServerSettings = ServerSettings{
},
Login: LoginSettings{
LoginWith: LoginWith{
Phone: true,
Username: true,
Federated: false,
Phone: true,
Username: true,
Federated: false,
FederatedOIDC: false,
},
TFAType: TFATypeApp,
TFAResendTimeout: 30,
Expand Down
2 changes: 2 additions & 0 deletions web/api/app_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type appSettings struct {
LoginWith model.LoginWith `json:"loginWith"`
FederatedProviders []string `json:"federatedProviders"`
CustomEmailTemplates bool `json:"customEmailTemplates"`
FederatedOIDCInitURL string `json:"federatedOIDCInitURL"`
}

// GetAppSettings return app settings
Expand Down Expand Up @@ -49,6 +50,7 @@ func (ar *Router) GetAppSettings() http.HandlerFunc {
LoginWith: ar.SupportedLoginWays,
FederatedProviders: make([]string, 0, len(app.FederatedProviders)),
CustomEmailTemplates: app.CustomEmailTemplates,
FederatedOIDCInitURL: app.OIDCSettings.InitURL,
}

for k := range app.FederatedProviders {
Expand Down
10 changes: 10 additions & 0 deletions web/api/federated_oidc_login.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ func (ar *Router) OIDCLogin(w http.ResponseWriter, r *http.Request) {
return
}

if !ar.SupportedLoginWays.FederatedOIDC {
ar.Error(w, locale, http.StatusBadRequest, l.ErrorFederatedOidcDisabled)
return
}

redirect := r.URL.Query().Get("redirectUrl")
if len(redirect) == 0 {
ar.Error(w, locale, http.StatusBadRequest, l.APIAPPFederatedProviderEmptyRedirect)
Expand Down Expand Up @@ -151,6 +156,11 @@ func (ar *Router) OIDCLoginComplete(w http.ResponseWriter, r *http.Request) {
return
}

if !ar.SupportedLoginWays.FederatedOIDC {
ar.Error(w, locale, http.StatusBadRequest, l.ErrorFederatedOidcDisabled)
return
}

claims, fsess, err := ar.completeOIDCAuth(r, app)
if err != nil {
ar.ErrorResponse(w, err)
Expand Down
4 changes: 4 additions & 0 deletions web/api/federated_oidc_login_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ var testServerSettings = model.DefaultServerSettings

func (tc testConfig) LoadServerSettings(validate bool) (model.ServerSettings, []error) {
testServerSettings.KeyStorage.Local.Path = "../../jwt/test_artifacts/private.pem"
testServerSettings.Login.LoginWith.FederatedOIDC = true
return testServerSettings, nil
}

Expand All @@ -62,6 +63,9 @@ func init() {
}

rs := api.RouterSettings{
LoginWith: model.LoginWith{
FederatedOIDC: true,
},
Server: testServer,
Cors: cors.New(model.DefaultCors),
}
Expand Down
12 changes: 6 additions & 6 deletions web/management/auth_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,30 @@ func (ar *Router) AuthMiddleware(next http.Handler) http.Handler {
locale := r.Header.Get("Accept-Language")

if len(r.Header[KeyIDHeaderKey]) != 1 || len(r.Header[KeyIDHeaderKey][0]) == 0 {
ar.Error(w, locale, http.StatusBadRequest, l.ErrorMANoKeyID)
ar.Error(w, locale, http.StatusBadRequest, l.ErrorNativeLoginMaNoKeyID)
return
}

keyID := r.Header[KeyIDHeaderKey][0]
key, err := ar.stor.GetKey(r.Context(), keyID)
if err != nil {
ar.Error(w, locale, http.StatusBadRequest, l.ErrorMAErrorGettingKeyWithID, keyID, err)
ar.Error(w, locale, http.StatusBadRequest, l.ErrorNativeLoginMaErrorKeyWithID, keyID, err)
return
}

if key.Active == false {
ar.Error(w, locale, http.StatusBadRequest, l.ErrorMAErrorInactiveKey)
if !key.Active {
ar.Error(w, locale, http.StatusBadRequest, l.ErrorNativeLoginMaKeyInactive)
return
}

if key.ValidTill != nil && time.Now().After(*key.ValidTill) {
ar.Error(w, locale, http.StatusBadRequest, l.ErrorMAErrorExpiredKey)
ar.Error(w, locale, http.StatusBadRequest, l.ErrorNativeLoginMaKeyExpired)
return
}

err = sig.VerifySignature(r, []byte(key.Secret))
if err != nil {
ar.Error(w, locale, http.StatusBadRequest, l.ErrorMAErrorInvalidSignature, err)
ar.Error(w, locale, http.StatusBadRequest, l.ErrorNativeLoginMaErrorSignature, err)
return
}
next.ServeHTTP(w, r)
Expand Down

0 comments on commit 447686f

Please sign in to comment.