Express Authenticators
Third party authenticator module re-written in Typescript
- Support OAuth and OAuth2 protocols without any dependency
- Re-written the oauth/oauth2 protocols in modern Typescript. Very easy to be maintained
- Support fetching user profile for various providers: Goolge, Facebook, Twitter, Instagram, Tumblr, Github, LinkedIn, Pinterest, Foursquare.
Usage
- With
yarn
: yarn add express-authenticators
. - With
npm
: npm install --save express-authenticators
.
API references
This module required express-session
middleware to be pre-configured
Exported classes:
-
FacebookAuthenticator
, FoursquareAuthenticator
, GithubAuthenticator
, GoogleAuthenticator
, InstagramAuthenticator
, LinkedInAuthenticator
, PinterestAuthenticator
, TumblrAuthenticator
, TwitterAuthenticator
.
All these classes have same interface, they all inherit OAuth2 or OAuth classes
constructor(option: {
clientID: 'app id',
clientSecret: 'app secret',
redirectUri: `https://example.com/auth/<provider>/callback`
})
authenticate(req: Request, res: Response): Promise<void> | void
callback(req: Request): Promise<TokenType> | TokenType
fetchProfile(tokenSet: TokenType): Promise<{
id?: string
email?: string
emailVerified?: boolean
first?: string
last?: string
avatar?: string
raw: any
}>
authenticate
: redirect middleware
If there is no error, this middleware will redirect the user to the provider website.
Eventually, redirect back to our pre-configured redirectUri
with appropriate user privilege.
callback
: take the request and return a promise which returns a token for profile fetching.
This function should be called in the callback url handler. Check example at the end of this readme.
fetchProfile
: provider-specific profile fetcher using the token returned by callback
.
In principle these classes have authenticate
and callback
methods.
However, I recommend you use the provider-specific classes described above.
If you need additional provider, clone the other providers' implementations then make your own.
Here are two sample implementations of FacebookAuthenticator
(OAuth2
), and TwitterAuthenticator
(OAuth
)
class FacebookAuthenticator extends OAuth2 implements IOAuthProfileFetcher<string> {
fetchProfile = fetchFacebookProfile
constructor(options: {
clientID: string
clientSecret: string
redirectUri: string
scope?: string
}) {
super({
consentURL: 'https://www.facebook.com/v6.0/dialog/oauth',
tokenURL: 'https://graph.facebook.com/v6.0/oauth/access_token',
scope: ['email'].join(','),
...options,
}, {
ignoreGrantType: true,
tokenRequestMethod: TokenRequestMethod.GET,
includeStateInAccessToken: false
})
}
}
class TwitterAuthenticator extends OAuth implements IOAuthProfileFetcher<IOAuthTokenSet> {
constructor(config: {
clientID: string
clientSecret: string
redirectUri: string
}) {
super({
consumerKey: config.clientID,
consumerSecret: config.clientSecret,
callbackUrl: config.redirectUri,
requestTokenUrl: 'https://api.twitter.com/oauth/request_token',
accessTokenUrl: 'https://api.twitter.com/oauth/access_token',
authorizeUrl: 'https://api.twitter.com/oauth/authorize',
signingMethod: OAuthSigningMethod.Hmac,
})
}
async fetchProfile(tokenSet: IOAuthTokenSet){
const response = await this.signAndFetch(
'https://api.twitter.com/1.1/account/verify_credentials.json',
{
qs: { include_email: true},
},
tokenSet
)
if (!response.ok) throw new OAuthProfileError(await response.text())
const profile = await response.json()
if (!profile.id_str) throw new OAuthProfileError('Invalid Twitter profile ID')
return {
id: profile.id_str,
raw: profile,
avatar: profile.profile_image_url_https
|| profile.profile_image_url
|| profile.profile_background_image_url_https
|| profile.profile_background_image_url,
first: profile.name || profile.screen_name,
email: profile.email,
emailVerified: !!profile.email,
}
}
}
Usage example
import {
FacebookAuthenticator,
FoursquareAuthenticator,
GithubAuthenticator,
GoogleAuthenticator,
InstagramAuthenticator,
LinkedInAuthenticator,
PinterestAuthenticator,
TumblrAuthenticator,
TwitterAuthenticator,
OAuth2,
OAuth
} from 'express-authenticators'
import express from 'express'
import session from 'express-session'
import asyncMiddleware from 'middleware-async'
const app = express()
app.use(session())
const facebookAuth = new FacebookAuthenticator({
clientID: 'facebook app id',
clientSecret: 'facebook app secret',
redirectUri: `https://example.com/auth/facebook/callback`,
})
app.get(
'/auth/facebook',
(req, res, next) => {
req.session!.someInfo = 'my info'
facebookAuth.authenticate(req, res, next)
}
)
app.get(
`/auth/facebook/callback`,
asyncMiddleware(async (req, res) => {
const token = await facebookAuth.callback(req)
const profile = await facebookAuth.fetchProfile(token)
console.log('got profile', profile)
res.send(JSON.stringify(profile))
})
)