diff --git a/.changeset/fuzzy-geckos-beam.md b/.changeset/fuzzy-geckos-beam.md new file mode 100644 index 0000000000..41ee57d9b0 --- /dev/null +++ b/.changeset/fuzzy-geckos-beam.md @@ -0,0 +1,28 @@ +--- +'example-app': patch +'@backstage/plugin-auth-backend': patch +--- + +Add configurable `scope` for oauth2 auth provider. + +Some OAuth2 providers require certain scopes to facilitate a user sign-in using the Authorization Code flow. +This change adds the optional `scope` key to auth.providers.oauth2. An example is: + +```yaml +auth: + providers: + oauth2: + development: + clientId: + $env: DEV_OAUTH2_CLIENT_ID + clientSecret: + $env: DEV_OAUTH2_CLIENT_SECRET + authorizationUrl: + $env: DEV_OAUTH2_AUTH_URL + tokenUrl: + $env: DEV_OAUTH2_TOKEN_URL + scope: saml-login-selector openid profile email +``` + +This tells the OAuth 2.0 AS to perform a SAML login and return OIDC information include the `profile` +and `email` claims as part of the ID Token. diff --git a/app-config.yaml b/app-config.yaml index 5240a050a8..02970f4b46 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -305,6 +305,8 @@ auth: $env: AUTH_OAUTH2_AUTH_URL tokenUrl: $env: AUTH_OAUTH2_TOKEN_URL + scope: + $env: AUTH_OAUTH2_SCOPE oidc: development: metadataUrl: diff --git a/docs/auth/auth-backend-classes.md b/docs/auth/auth-backend-classes.md index 424869196d..a99ca119f0 100644 --- a/docs/auth/auth-backend-classes.md +++ b/docs/auth/auth-backend-classes.md @@ -76,14 +76,16 @@ by also providing the `cert` configuration. ### Configuration -Each authentication provider (except SAML) needs five parameters: an OAuth -client ID, a client secret, an authorization endpoint, a token endpoint, and an -app origin. The app origin is the URL at which the frontend of the application -is hosted, and it is read from the `app.baseUrl` config. This is required -because the application opens a popup window to perform the authentication, and -once the flow is completed, the popup window sends a `postMessage` to the -frontend application to indicate the result of the operation. Also this URL is -used to verify that authentication requests are coming from only this endpoint. +Each authentication provider (except SAML) needs six parameters: an OAuth client +ID, a client secret, an authorization endpoint, a token endpoint, an optional +list of scopes (as a string separated by spaces) that may be required by the +OAuth2 Server to enable end-user sign-on, and an app origin. The app origin is +the URL at which the frontend of the application is hosted, and it is read from +the `app.baseUrl` config. This is required because the application opens a popup +window to perform the authentication, and once the flow is completed, the popup +window sends a `postMessage` to the frontend application to indicate the result +of the operation. Also this URL is used to verify that authentication requests +are coming from only this endpoint. These values are configured via the `app-config.yaml` present in the root of your app folder. @@ -109,6 +111,18 @@ auth: development: clientId: $env: + oauth2: + development: + clientId: + $env: AUTH_OAUTH2_CLIENT_ID + clientSecret: + $env: AUTH_OAUTH2_CLIENT_SECRET + authorizationUrl: + $env: AUTH_OAUTH2_AUTH_URL + tokenUrl: + $env: AUTH_OAUTH2_TOKEN_URL + scope: + $env: AUTH_OAUTH2_SCOPE saml: entryPoint: $env: AUTH_SAML_ENTRY_POINT diff --git a/packages/app/src/identityProviders.ts b/packages/app/src/identityProviders.ts index 01828b1405..6f45f9ba32 100644 --- a/packages/app/src/identityProviders.ts +++ b/packages/app/src/identityProviders.ts @@ -22,6 +22,7 @@ import { samlAuthApiRef, microsoftAuthApiRef, oneloginAuthApiRef, + oauth2ApiRef, oidcAuthApiRef, } from '@backstage/core'; @@ -32,6 +33,12 @@ export const providers = [ message: 'Sign In using OpenId Connect', apiRef: oidcAuthApiRef, }, + { + id: 'oauth2-auth-provider', + title: 'OAuth 2.0', + message: 'Sign In using OAuth 2.0', + apiRef: oauth2ApiRef, + }, { id: 'google-auth-provider', title: 'Google', diff --git a/plugins/auth-backend/config.d.ts b/plugins/auth-backend/config.d.ts index 84f71b52b9..6d54ac5a3c 100644 --- a/plugins/auth-backend/config.d.ts +++ b/plugins/auth-backend/config.d.ts @@ -58,7 +58,14 @@ export interface Config { development: { [key: string]: string }; }; oauth2?: { - development: { [key: string]: string }; + development: { + clientId: string; + clientSecret: string; + callbackUrl: string; + authorizationUrl: string; + tokenUrl: string; + scope?: string; + }; }; oidc?: { development: { [key: string]: string }; diff --git a/plugins/auth-backend/src/providers/oauth2/provider.ts b/plugins/auth-backend/src/providers/oauth2/provider.ts index 04cb7670f3..a44c4fb50b 100644 --- a/plugins/auth-backend/src/providers/oauth2/provider.ts +++ b/plugins/auth-backend/src/providers/oauth2/provider.ts @@ -44,6 +44,7 @@ type PrivateInfo = { export type OAuth2AuthProviderOptions = OAuthProviderOptions & { authorizationUrl: string; tokenUrl: string; + scope?: string; }; export class OAuth2AuthProvider implements OAuthHandlers { @@ -58,6 +59,7 @@ export class OAuth2AuthProvider implements OAuthHandlers { authorizationURL: options.authorizationUrl, tokenURL: options.tokenUrl, passReqToCallback: false as true, + scope: options.scope, }, ( accessToken: any, @@ -168,6 +170,7 @@ export const createOAuth2Provider: AuthProviderFactory = ({ const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`; const authorizationUrl = envConfig.getString('authorizationUrl'); const tokenUrl = envConfig.getString('tokenUrl'); + const scope = envConfig.getOptionalString('scope'); const provider = new OAuth2AuthProvider({ clientId, @@ -175,6 +178,7 @@ export const createOAuth2Provider: AuthProviderFactory = ({ callbackUrl, authorizationUrl, tokenUrl, + scope, }); return OAuthAdapter.fromConfig(globalConfig, provider, {