diff --git a/config/config.go b/config/config.go index bc49bcf5..85ece6bb 100644 --- a/config/config.go +++ b/config/config.go @@ -68,6 +68,7 @@ type OIDC struct { AutoRegister bool LinkByUsername bool Scopes []string + IDPName string } type Configuration struct { @@ -117,6 +118,7 @@ func Get() (*Configuration, []FutureLog) { UsernameClaim: "preferred_username", AutoRegister: true, Scopes: []string{"openid", "profile", "email"}, + IDPName: "OIDC", }, } @@ -180,6 +182,7 @@ func Get() (*Configuration, []FutureLog) { add(parseBool(&c.OIDC.AutoRegister, EnvOIDCAutoRegister)) add(parseBool(&c.OIDC.LinkByUsername, EnvOIDCLinkByUsername)) add(parseList(&c.OIDC.Scopes, EnvOIDCScopes)) + add(parseString(&c.OIDC.IDPName, EnvOIDCIDPName)) add(parseString(&c.NoColor, EnvNoColor)) diff --git a/config/config_test.go b/config/config_test.go index 5ca4c966..548157fe 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -22,6 +22,7 @@ func TestConfigEnv(t *testing.T) { t.Setenv("GOTIFY_SERVER_CORS_ALLOWMETHODS", "GET,POST") t.Setenv("GOTIFY_SERVER_CORS_ALLOWHEADERS", "Authorization,content-type") t.Setenv("GOTIFY_SERVER_STREAM_ALLOWEDORIGINS", ".+.example.com,otherdomain.com") + t.Setenv("GOTIFY_OIDC_IDP_NAME", "Company XYZ SSO") conf, _ := Get() assert.Equal(t, 80, conf.Server.Port, "should use defaults") @@ -33,6 +34,7 @@ func TestConfigEnv(t *testing.T) { assert.Equal(t, []string{"GET", "POST"}, conf.Server.Cors.AllowMethods) assert.Equal(t, []string{"Authorization", "content-type"}, conf.Server.Cors.AllowHeaders) assert.Equal(t, []string{".+.example.com", "otherdomain.com"}, conf.Server.Stream.AllowedOrigins) + assert.Equal(t, "Company XYZ SSO", conf.OIDC.IDPName) } func TestLocalAuthDisabled(t *testing.T) { diff --git a/config/keys.go b/config/keys.go index e64aba96..c6bf7167 100644 --- a/config/keys.go +++ b/config/keys.go @@ -42,5 +42,6 @@ const ( EnvOIDCLinkByUsername = "GOTIFY_OIDC_LINK_BY_USERNAME" EnvLocalAuthEnabled = "GOTIFY_LOCALAUTH_ENABLED" EnvOIDCScopes = "GOTIFY_OIDC_SCOPES" + EnvOIDCIDPName = "GOTIFY_OIDC_IDP_NAME" EnvNoColor = "NOCOLOR" ) diff --git a/docs/spec.json b/docs/spec.json index 67de0871..5692a37b 100644 --- a/docs/spec.json +++ b/docs/spec.json @@ -2947,7 +2947,8 @@ "version", "register", "localAuth", - "oidc" + "oidc", + "oidcIdpName" ], "properties": { "localAuth": { @@ -2962,6 +2963,12 @@ "x-go-name": "Oidc", "example": true }, + "oidcIdpName": { + "description": "Name of the OIDC identity provider.", + "type": "string", + "x-go-name": "OIDCIDPName", + "example": "OIDC" + }, "register": { "description": "If registration is enabled.", "type": "boolean", diff --git a/gotify-server.env.example b/gotify-server.env.example index f205bf05..14c13e3f 100644 --- a/gotify-server.env.example +++ b/gotify-server.env.example @@ -228,6 +228,13 @@ # Type: boolean # GOTIFY_LOCALAUTH_ENABLED=true +# Name of the OIDC identity provider displayed in the login and elevation UI. +# Only used if GOTIFY_OIDC_ENABLED is true. Defaults to OIDC. +# +# Type: text +# Example: Company XYZ SSO +# GOTIFY_OIDC_IDP_NAME=OIDC + # Database driver to use. For mysql and postgres the target database must # already exist and the configured user must have sufficient permissions. # diff --git a/model/gotifyinfo.go b/model/gotifyinfo.go index 38692adc..526276ef 100644 --- a/model/gotifyinfo.go +++ b/model/gotifyinfo.go @@ -24,4 +24,9 @@ type GotifyInfo struct { // required: true // example: true Oidc bool `json:"oidc"` + // Name of the OIDC identity provider. + // + // required: true + // example: OIDC + OIDCIDPName string `json:"oidcIdpName"` } diff --git a/router/router.go b/router/router.go index 89505471..e65842c0 100644 --- a/router/router.go +++ b/router/router.go @@ -120,7 +120,7 @@ func Create(db *database.GormDatabase, vInfo *model.VersionInfo, conf *config.Co userChangeNotifier.OnUserDeleted(pluginManager.RemoveUser) userChangeNotifier.OnUserAdded(pluginManager.InitializeForUserID) - ui.Register(g, *vInfo, conf.Registration, conf.LocalAuthEnabled, conf.OIDC.Enabled) + ui.Register(g, *vInfo, conf.Registration, conf.LocalAuthEnabled, conf.OIDC.Enabled, conf.OIDC.IDPName) if conf.OIDC.Enabled { oidcHandler := api.NewOIDC(conf, db, userChangeNotifier) @@ -191,7 +191,13 @@ func Create(db *database.GormDatabase, vInfo *model.VersionInfo, conf *config.Co // schema: // $ref: "#/definitions/GotifyInfo" g.GET("gotifyinfo", func(ctx *gin.Context) { - ctx.JSON(200, &model.GotifyInfo{Version: vInfo.Version, Oidc: conf.OIDC.Enabled, Register: conf.Registration, LocalAuth: conf.LocalAuthEnabled}) + ctx.JSON(200, &model.GotifyInfo{ + Version: vInfo.Version, + Oidc: conf.OIDC.Enabled, + Register: conf.Registration, + LocalAuth: conf.LocalAuthEnabled, + OIDCIDPName: conf.OIDC.IDPName, + }) }) g.Group("/").Use(authentication.RequireApplicationOrClient).POST("/message", messageHandler.CreateMessage) diff --git a/router/router_test.go b/router/router_test.go index 58daed95..cd6f7864 100644 --- a/router/router_test.go +++ b/router/router_test.go @@ -42,7 +42,11 @@ func (s *IntegrationSuite) BeforeTest(string, string) { g, closable := Create( s.db.GormDatabase, &model.VersionInfo{Version: "1.0.0", BuildDate: "2018-02-20-17:30:47", Commit: "asdasds"}, - &config.Configuration{PassStrength: 5, LocalAuthEnabled: true}, + &config.Configuration{ + PassStrength: 5, + LocalAuthEnabled: true, + OIDC: config.OIDC{IDPName: "Company XYZ SSO"}, + }, ) s.closable = closable s.server = httptest.NewServer(g) @@ -60,6 +64,12 @@ func (s *IntegrationSuite) TestVersionInfo() { doRequestAndExpect(s.T(), req, 200, `{"version":"1.0.0", "commit":"asdasds", "buildDate":"2018-02-20-17:30:47"}`) } +func (s *IntegrationSuite) TestGotifyInfo() { + req := s.newRequest("GET", "gotifyinfo", "") + + doRequestAndExpect(s.T(), req, 200, `{"version":"1.0.0", "oidc":false, "register":false, "localAuth":true, "oidcIdpName":"Company XYZ SSO"}`) +} + func (s *IntegrationSuite) TestHeaderInProd() { mode.Set(mode.Prod) req := s.newRequest("GET", "version", "") diff --git a/ui/serve.go b/ui/serve.go index 12e32590..afe2e10d 100644 --- a/ui/serve.go +++ b/ui/serve.go @@ -16,19 +16,28 @@ import ( var box embed.FS type uiConfig struct { - Register bool `json:"register"` - Version model.VersionInfo `json:"version"` - LocalAuth bool `json:"localAuth"` - OIDC bool `json:"oidc"` + Register bool `json:"register"` + Version model.VersionInfo `json:"version"` + LocalAuth bool `json:"localAuth"` + OIDC bool `json:"oidc"` + OIDCIDPName string `json:"oidcIdpName"` } // Register registers the ui on the root path. -func Register(r *gin.Engine, version model.VersionInfo, register, localAuthEnabled, oidcEnabled bool) { +func Register( + r *gin.Engine, + version model.VersionInfo, + register bool, + localAuthEnabled bool, + oidcEnabled bool, + oidcIDPName string, +) { uiConfigBytes, err := json.Marshal(uiConfig{ - Version: version, - Register: register, - LocalAuth: localAuthEnabled, - OIDC: oidcEnabled, + Version: version, + Register: register, + LocalAuth: localAuthEnabled, + OIDC: oidcEnabled, + OIDCIDPName: oidcIDPName, }) if err != nil { panic(err) diff --git a/ui/src/common/ElevationForm.tsx b/ui/src/common/ElevationForm.tsx index bed7c620..cb5db113 100644 --- a/ui/src/common/ElevationForm.tsx +++ b/ui/src/common/ElevationForm.tsx @@ -18,6 +18,7 @@ const ElevationForm = observer(() => { const localAuthEnabled = config.get('localAuth'); const oidcEnabled = config.get('oidc'); const oidcPending = elevateStore.oidcElevatePending; + const oidcIdpName = config.get('oidcIdpName'); const handleLocalElevate = async () => { try { @@ -91,7 +92,7 @@ const ElevationForm = observer(() => { color="primary" fullWidth onClick={() => elevateStore.oidcElevate(ElevateDuration)}> - Elevate via OIDC + {`Elevate via ${oidcIdpName}`} )} diff --git a/ui/src/config.ts b/ui/src/config.ts index cfe75d52..be57bd21 100644 --- a/ui/src/config.ts +++ b/ui/src/config.ts @@ -6,6 +6,7 @@ export interface IConfig { version: IVersion; oidc: boolean; localAuth: boolean; + oidcIdpName: string; } declare global { @@ -20,6 +21,7 @@ const config: IConfig = { version: {commit: 'unknown', buildDate: 'unknown', version: 'unknown'}, oidc: false, localAuth: true, + oidcIdpName: 'OIDC', ...window.config, }; diff --git a/ui/src/user/Login.tsx b/ui/src/user/Login.tsx index 5f1ac4b1..5dc819cc 100644 --- a/ui/src/user/Login.tsx +++ b/ui/src/user/Login.tsx @@ -19,6 +19,8 @@ const Login = observer(() => { const navigate = useNavigate(); const localAuthEnabled = config.get('localAuth'); const oidcEnabled = config.get('oidc'); + const oidcIdpName = config.get('oidcIdpName'); + React.useEffect(() => { if (currentUser.loggedIn) { navigate('/'); @@ -103,7 +105,7 @@ const Login = observer(() => { size="large" color="primary" style={{marginBottom: 5}}> - Login with OIDC + {`Login with ${oidcIdpName}`} )}