diff --git a/README.md b/README.md index 634614c7..800206bf 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,12 @@ import { AuthModule, LogLevel } from 'angular-auth-oidc-client'; export class AppModule {} ``` +When using `silentRenew` together with `useRefreshToken`, requesting the +`offline_access` scope is common and remains the default recommendation. +Some providers support refresh token renewal in the browser without +`offline_access`. In those cases, you can suppress the configuration warning +with `disableRefreshTokenOfflineAccessScopeWarning: true`. + And call the method `checkAuth()` from your `app.component.ts`. The method `checkAuth()` is needed to process the redirect from your Security Token Service and set the correct states. This method must be used to ensure the correct functioning of the library. ```ts diff --git a/projects/angular-auth-oidc-client/src/lib/config/default-config.ts b/projects/angular-auth-oidc-client/src/lib/config/default-config.ts index 3955a65d..5236490f 100644 --- a/projects/angular-auth-oidc-client/src/lib/config/default-config.ts +++ b/projects/angular-auth-oidc-client/src/lib/config/default-config.ts @@ -18,6 +18,7 @@ export const DEFAULT_CONFIG: OpenIdConfiguration = { silentRenewTimeoutInSeconds: 20, renewTimeBeforeTokenExpiresInSeconds: 0, useRefreshToken: false, + disableRefreshTokenOfflineAccessScopeWarning: false, usePushedAuthorisationRequests: false, ignoreNonceAfterRefresh: false, postLoginRoute: '/', diff --git a/projects/angular-auth-oidc-client/src/lib/config/openid-configuration.ts b/projects/angular-auth-oidc-client/src/lib/config/openid-configuration.ts index 1ecbdac8..6a4e8c99 100644 --- a/projects/angular-auth-oidc-client/src/lib/config/openid-configuration.ts +++ b/projects/angular-auth-oidc-client/src/lib/config/openid-configuration.ts @@ -91,6 +91,12 @@ export interface OpenIdConfiguration { * Default value is false. */ useRefreshToken?: boolean; + /** + * Suppresses the warning that recommends the `offline_access` scope when + * using refresh tokens together with silent renew. Some providers support + * this setup without requesting `offline_access`. + */ + disableRefreshTokenOfflineAccessScopeWarning?: boolean; /** * Activates Pushed Authorisation Requests for login and popup login. * Not compatible with iframe renew. @@ -209,5 +215,5 @@ export interface OpenIdConfiguration { /** * Disable cleaning up the popup when receiving invalid messages */ - disableCleaningPopupOnInvalidMessage?: boolean + disableCleaningPopupOnInvalidMessage?: boolean; } diff --git a/projects/angular-auth-oidc-client/src/lib/config/validation/rules/use-offline-scope-with-silent-renew.rule.spec.ts b/projects/angular-auth-oidc-client/src/lib/config/validation/rules/use-offline-scope-with-silent-renew.rule.spec.ts new file mode 100644 index 00000000..19b50520 --- /dev/null +++ b/projects/angular-auth-oidc-client/src/lib/config/validation/rules/use-offline-scope-with-silent-renew.rule.spec.ts @@ -0,0 +1,53 @@ +import { OpenIdConfiguration } from '../../openid-configuration'; +import { useOfflineScopeWithSilentRenew } from './use-offline-scope-with-silent-renew.rule'; + +describe('useOfflineScopeWithSilentRenew', () => { + const createConfig = ( + overrides: Partial = {} + ): OpenIdConfiguration => ({ + silentRenew: true, + useRefreshToken: true, + scope: 'openid profile', + ...overrides, + }); + + it('returns a warning when refresh tokens are used without offline_access', () => { + const result = useOfflineScopeWithSilentRenew(createConfig()); + + expect(result).toEqual({ + result: false, + messages: [ + 'When using silent renew and refresh tokens the `offline_access` scope is often required. If your provider supports this without it, set `disableRefreshTokenOfflineAccessScopeWarning` to suppress this warning.', + ], + level: 'warning', + }); + }); + + it('returns a positive result when the warning is disabled explicitly', () => { + const result = useOfflineScopeWithSilentRenew( + createConfig({ + disableRefreshTokenOfflineAccessScopeWarning: true, + }) + ); + + expect(result).toEqual({ + result: true, + messages: [], + level: 'none', + }); + }); + + it('returns a positive result when offline_access is included', () => { + const result = useOfflineScopeWithSilentRenew( + createConfig({ + scope: 'openid profile offline_access', + }) + ); + + expect(result).toEqual({ + result: true, + messages: [], + level: 'none', + }); + }); +}); diff --git a/projects/angular-auth-oidc-client/src/lib/config/validation/rules/use-offline-scope-with-silent-renew.rule.ts b/projects/angular-auth-oidc-client/src/lib/config/validation/rules/use-offline-scope-with-silent-renew.rule.ts index 71605737..7805a5c1 100644 --- a/projects/angular-auth-oidc-client/src/lib/config/validation/rules/use-offline-scope-with-silent-renew.rule.ts +++ b/projects/angular-auth-oidc-client/src/lib/config/validation/rules/use-offline-scope-with-silent-renew.rule.ts @@ -6,14 +6,21 @@ export const useOfflineScopeWithSilentRenew = ( ): RuleValidationResult => { const hasRefreshToken = passedConfig.useRefreshToken; const hasSilentRenew = passedConfig.silentRenew; + const disableOfflineAccessScopeWarning = + passedConfig.disableRefreshTokenOfflineAccessScopeWarning; const scope = passedConfig.scope || ''; const hasOfflineScope = scope.split(' ').includes('offline_access'); - if (hasRefreshToken && hasSilentRenew && !hasOfflineScope) { + if ( + hasRefreshToken && + hasSilentRenew && + !hasOfflineScope && + !disableOfflineAccessScopeWarning + ) { return { result: false, messages: [ - 'When using silent renew and refresh tokens please set the `offline_access` scope', + 'When using silent renew and refresh tokens the `offline_access` scope is often required. If your provider supports this without it, set `disableRefreshTokenOfflineAccessScopeWarning` to suppress this warning.', ], level: 'warning', };