Gathering detailed insights and metrics for remix-auth-oauth2-pkce
Gathering detailed insights and metrics for remix-auth-oauth2-pkce
Gathering detailed insights and metrics for remix-auth-oauth2-pkce
Gathering detailed insights and metrics for remix-auth-oauth2-pkce
npm install remix-auth-oauth2-pkce
Typescript
Module System
Node Version
NPM Version
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
3
2
29
A strategy to use and implement OAuth2 framework for authentication with federated services like Google, Facebook, GitHub, etc.
Runtime | Has Support |
---|---|
Node.js | ✅ |
Cloudflare | ✅ |
1npm add remix-auth-oauth2-pkce
You can use this strategy by adding it to your authenticator instance and configuring the correct endpoints.
1export let authenticator = new Authenticator<User>(sessionStorage);
2
3authenticator.use(
4 new OAuth2Strategy(
5 {
6 authorizationURL: "https://provider.com/oauth2/authorize",
7 tokenURL: "https://provider.com/oauth2/token",
8 clientID: process.env.CLIENT_ID,
9 callbackURL: "https://example.app/auth/callback",
10 scope: [],
11 useBasicAuthenticationHeader: false // defaults to false
12 },
13 async ({ accessToken, refreshToken, extraParams, profile, context }) => {
14 // here you can use the params above to get the user and return it
15 // what you do inside this and how you find the user is up to you
16 return await getUser(
17 accessToken,
18 refreshToken,
19 extraParams,
20 profile,
21 context
22 );
23 }
24 ),
25 // this is optional, but if you setup more than one OAuth2 instance you will
26 // need to set a custom name to each one
27 "provider-name"
28);
You can use this strategy as a base class for another strategy using the OAuth2 framework. That way, you wouldn't need to implement the whole OAuth2 flow yourself.
The OAuth2Strategy
will handle the whole flow for you and let you replace parts of it where you need.
Let's see how the Auth0Strategy
is implemented using the OAuth2Strategy
as a base.
1// We need to import from Remix Auth the type of the strategy verify callback 2import type { StrategyVerifyCallback } from "remix-auth"; 3// We need to import the OAuth2Strategy, the verify params and the profile interfaces 4import type { 5 OAuth2Profile, 6 OAuth2StrategyVerifyParams, 7} from "remix-auth-oauth2-pkce"; 8import { OAuth2Strategy } from "remix-auth-oauth2-pkce"; 9 10// These are the custom options we need from the developer to use the strategy 11export interface Auth0StrategyOptions { 12 domain: string; 13 clientID: string; 14 clientSecret: string; 15 callbackURL: string; 16} 17 18// This interface declare what extra params we will get from Auth0 on the 19// verify callback 20export interface Auth0ExtraParams extends Record<string, string | number> { 21 id_token: string; 22 scope: string; 23 expires_in: 86_400; 24 token_type: "Bearer"; 25} 26 27// The Auth0Profile extends the OAuth2Profile with the extra params and mark 28// some of them as required 29export interface Auth0Profile extends OAuth2Profile { 30 id: string; 31 displayName: string; 32 name: { 33 familyName: string; 34 givenName: string; 35 middleName: string; 36 }; 37 emails: Array<{ value: string }>; 38 photos: Array<{ value: string }>; 39 _json: { 40 sub: string; 41 name: string; 42 given_name: string; 43 family_name: string; 44 middle_name: string; 45 nickname: string; 46 preferred_username: string; 47 profile: string; 48 picture: string; 49 website: string; 50 email: string; 51 email_verified: boolean; 52 gender: string; 53 birthdate: string; 54 zoneinfo: string; 55 locale: string; 56 phone_number: string; 57 phone_number_verified: boolean; 58 address: { 59 country: string; 60 }; 61 updated_at: string; 62 }; 63} 64 65// And we create our strategy extending the OAuth2Strategy, we also need to 66// pass the User as we did on the FormStrategy, we pass the Auth0Profile and the 67// extra params 68export class Auth0Strategy<User> extends OAuth2Strategy< 69 User, 70 Auth0Profile, 71 Auth0ExtraParams 72> { 73 // The OAuth2Strategy already has a name but we override it to be specific of 74 // the service we are using 75 name = "auth0"; 76 77 private userInfoURL: string; 78 79 // We receive our custom options and our verify callback 80 constructor( 81 options: Auth0StrategyOptions, 82 // Here we type the verify callback as a StrategyVerifyCallback receiving 83 // the User type and the OAuth2StrategyVerifyParams with the Auth0Profile 84 // and the Auth0ExtraParams 85 // This way, when using the strategy the verify function will receive as 86 // params an object with accessToken, refreshToken, extraParams and profile. 87 // The latest two matching the types of Auth0Profile and Auth0ExtraParams. 88 verify: StrategyVerifyCallback< 89 User, 90 OAuth2StrategyVerifyParams<Auth0Profile, Auth0ExtraParams> 91 > 92 ) { 93 // And we pass the options to the super constructor using our own options 94 // to generate them, this was we can ask less configuration to the developer 95 // using our strategy 96 super( 97 { 98 authorizationURL: `https://${options.domain}/authorize`, 99 tokenURL: `https://${options.domain}/oauth/token`, 100 clientID: options.clientID, 101 clientSecret: options.clientSecret, 102 callbackURL: options.callbackURL, 103 }, 104 verify 105 ); 106 107 this.userInfoURL = `https://${options.domain}/userinfo`; 108 this.scope = options.scope || "openid profile email"; 109 this.audience = options.audience; 110 } 111 112 // We override the protected authorizationParams method to return a new 113 // URLSearchParams with custom params we want to send to the authorizationURL. 114 // Here we add the scope so Auth0 can use it, you can pass any extra param 115 // you need to send to the authorizationURL here base on your provider. 116 protected authorizationParams() { 117 const urlSearchParams: Record<string, string> = { 118 scope: this.scope, 119 }; 120 121 if (this.audience) { 122 urlSearchParams.audience = this.audience; 123 } 124 125 return new URLSearchParams(urlSearchParams); 126 } 127 128 // We also override how to use the accessToken to get the profile of the user. 129 // Here we fetch a Auth0 specific URL, get the profile data, and build the 130 // object based on the Auth0Profile interface. 131 protected async userProfile(accessToken: string): Promise<Auth0Profile> { 132 let response = await fetch(this.userInfoURL, { 133 headers: { Authorization: `Bearer ${accessToken}` }, 134 }); 135 136 let data: Auth0Profile["_json"] = await response.json(); 137 138 let profile: Auth0Profile = { 139 provider: "auth0", 140 displayName: data.name, 141 id: data.sub, 142 name: { 143 familyName: data.family_name, 144 givenName: data.given_name, 145 middleName: data.middle_name, 146 }, 147 emails: [{ value: data.email }], 148 photos: [{ value: data.picture }], 149 _json: data, 150 }; 151 152 return profile; 153 } 154}
And that's it, thanks to the OAuth2Strategy
we don't need to implement the whole OAuth2 flow ourselves and can focus on the unique parts of our strategy which is the user profile and extra params our provider may require us to send.
No vulnerabilities found.
No security vulnerabilities found.