README
OAuth2 Service
Table of Contents
See TOC menu above.
Introduction
Hey folks! This is a vendasta-centric oauth2 angular service! It can help you out with the following things:
- Adding authentication to your app -- It can authenticate the user with IAM using sso's oauth2 integration!
- It doubles as a
SessionService
for your angular app, so all your sdks and api calls should just work™ - It provides a helpful
canActivate
route guard for you to use in your routes, which can detect unauthenticated users and will seamlessly log them in and redirect back to the desired page.
Sound good? Keep reading for installation instructions:
Installation
Install @vendasta/oauth2
in your Angular app.
Dependencies
First things first:
npm install --save @vendasta/oauth2 angular-oauth2-oidc
You'll also need to have the following list of peer dependencies, but you likely already have most of those:
npm install --save \
typescript \
rxjs \
@angular/common \
@angular/core \
@angular/router \
angular-oauth2-oidc \
@vendasta/uikit \
@vendasta/core \
@vendasta/partner
Nice!
Module Setup
Now we need to provide the service in your app. This should be as easy as importing the OAuth2Module in your app.module.ts
and providing OAuthStorage
and OAuth2ServiceConfigToken
dependencies.
We'll also want to specify that we're using the OAuth2Service
for our sessions by providing it as the SessionService
import { OAuth2Service, OAuth2Module } from '@vendasta/oauth2';
import { OAuthModule, OAuthStorage } from 'angular-oauth2-oidc';
@NgModule({
imports: [
// ...
OAuth2Module,
OAuthModule.forRoot(),
],
providers: [
{ provide: OAuthStorage, useFactory: (): OAuthStorage => window.localStorage },
// Use the OAuth2Service service to handle sessions
{ provide: SessionService, useExisting: OAuth2Service },
],
})
export class AppModule {
}
Great!
Configuration
NOTE See the SSO frontend auth docs for more details.
Now we've got our service set up, but you'll need to configure it so it knows how to authorize your users for your app.
If you haven't done so already, you'll need to create a service provider configuration for your app on demo and prod.
Once you've done that, you can create an oauth2 configuration factory (or export a config value, if it's static) somewhere in your app. Here's what the one for WSP Admin Center looks like:
export function oauth2ConfigFactory(): OAuth2ServiceConfig {
return {
scopes: ['admin'],
serviceProviderConfigs: {
[Environment.LOCAL]: {
serviceProviderId: 'wsp-admin-center',
redirectUri: 'https://localhost:4200',
silentRefreshRedirectUri: 'https://localhost:4200/silent-refresh.html',
clientId: 'c5a86f66-5ed1-4c11-82e3-157088e94831',
},
[Environment.DEMO]: {
serviceProviderId: 'wsp-admin-center',
redirectUri: 'https://wsp-admin-center-demo.apigateway.co',
silentRefreshRedirectUri: 'https://wsp-admin-center-demo.apigateway.co/silent-refresh.html',
clientId: 'c5a86f66-5ed1-4c11-82e3-157088e94831',
},
[Environment.PROD]: {
serviceProviderId: 'wsp-admin-center',
redirectUri: 'https://wsp-admin-center-prod.apigateway.co',
silentRefreshRedirectUri: 'https://wsp-admin-center-prod.apigateway.co/silent-refresh.html',
clientId: 'f6486e6d-740c-48b1-b46e-38923aba92b5',
},
},
customQueryParamsFunc: (next: ActivatedRouteSnapshot, _: RouterStateSnapshot) => ({
partner_id: (next.params as PartnerRouteParams).partnerId,
}),
};
}
You can then provide this configuration in your app.module.ts
, for example with useFactory
:
import { OAuth2ServiceConfigToken } from '@vendasta/oauth2'
@NgModule({
// ...
providers: [
{ provide: OAuth2ServiceConfigToken, useFactory: oauth2ConfigFactory },
],
}
Using the AuthGuard
The OAuth2Service implements the CanActivate
interface so it can be used directly as an route guard in your routing module.
This example requires the user to be logged in on every page except the logout page. Remember that ALL pages with the OAuth2Service route guard will redirect through an authentication flow if the app doesn't have a session for the user.
IMPORTANT SECURITY WARNING: do not rely on this route guard for performing authorization. Malicious actors can easily modify frontend code to bypass this kind of check.
You MUST perform backend authorization in each RPC that your app calls, and only use the route guard as a convenient way to ensure that users are directed to login if they don't have a valid session and are not redirected to login if their session is valid.
NOTE you must use OAuth2Service
as a route guard for the route that handles your oauth2 redirectUri
. This ensures that the code exchange flow works correctly, redirecting the user back to their originally-requested URL once they have a valid session.
const appRoutes = [
// ...
]
@NgModule({
imports: [
RouterModule.forRoot([
{path: 'logout', component: LogoutComponent},
{path: '', canActivate: [OAuth2Service], component: IndexComponent, children: appRoutes},
])],
exports: [RouterModule]
})
export class AppRoutingModule {
}
Configuring silent refresh
This oauth service uses a technique called "silent refresh" to allow refreshing tokens without the use of a Refresh Token (which are very difficult to use securely).
It does this by opening a hidden window with an iframe which silently goes through the oauth flow to get an up-to-date token.
See the SSO frontend auth docs for details.