This is a backport of #278 with the default value of `scope` changed to `undefined`. This is thus a fully backward-compatible change. Signed-off-by: Victor Berger <victor.berger@m4x.org>
		
			
				
	
	
		
			107 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			107 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict'
 | |
| 
 | |
| const Router = require('express').Router
 | |
| const passport = require('passport')
 | |
| const { Strategy, InternalOAuthError } = require('passport-oauth2')
 | |
| const config = require('../../../config')
 | |
| const { passportGeneralCallback } = require('../utils')
 | |
| 
 | |
| let oauth2Auth = module.exports = Router()
 | |
| 
 | |
| class OAuth2CustomStrategy extends Strategy {
 | |
|   constructor (options, verify) {
 | |
|     options.customHeaders = options.customHeaders || {}
 | |
|     super(options, verify)
 | |
|     this.name = 'oauth2'
 | |
|     this._userProfileURL = options.userProfileURL
 | |
|     this._oauth2.useAuthorizationHeaderforGET(true)
 | |
|   }
 | |
| 
 | |
|   userProfile (accessToken, done) {
 | |
|     this._oauth2.get(this._userProfileURL, accessToken, function (err, body, res) {
 | |
|       var json
 | |
| 
 | |
|       if (err) {
 | |
|         return done(new InternalOAuthError('Failed to fetch user profile', err))
 | |
|       }
 | |
| 
 | |
|       try {
 | |
|         json = JSON.parse(body)
 | |
|       } catch (ex) {
 | |
|         return done(new Error('Failed to parse user profile'))
 | |
|       }
 | |
| 
 | |
|       let profile = parseProfile(json)
 | |
|       profile.provider = 'oauth2'
 | |
| 
 | |
|       done(null, profile)
 | |
|     })
 | |
|   }
 | |
| }
 | |
| 
 | |
| function extractProfileAttribute (data, path) {
 | |
|   // can handle stuff like `attrs[0].name`
 | |
|   path = path.split('.')
 | |
|   for (const segment of path) {
 | |
|     const m = segment.match(/([\d\w]+)\[(.*)\]/)
 | |
|     data = m ? data[m[1]][m[2]] : data[segment]
 | |
|   }
 | |
|   return data
 | |
| }
 | |
| 
 | |
| function parseProfile (data) {
 | |
|   const username = extractProfileAttribute(data, config.oauth2.userProfileUsernameAttr)
 | |
|   const displayName = extractProfileAttribute(data, config.oauth2.userProfileDisplayNameAttr)
 | |
|   const email = extractProfileAttribute(data, config.oauth2.userProfileEmailAttr)
 | |
| 
 | |
|   return {
 | |
|     id: username,
 | |
|     username: username,
 | |
|     displayName: displayName,
 | |
|     email: email
 | |
|   }
 | |
| }
 | |
| 
 | |
| OAuth2CustomStrategy.prototype.userProfile = function (accessToken, done) {
 | |
|   this._oauth2.get(this._userProfileURL, accessToken, function (err, body, res) {
 | |
|     var json
 | |
| 
 | |
|     if (err) {
 | |
|       return done(new InternalOAuthError('Failed to fetch user profile', err))
 | |
|     }
 | |
| 
 | |
|     try {
 | |
|       json = JSON.parse(body)
 | |
|     } catch (ex) {
 | |
|       return done(new Error('Failed to parse user profile'))
 | |
|     }
 | |
| 
 | |
|     let profile = parseProfile(json)
 | |
|     profile.provider = 'oauth2'
 | |
| 
 | |
|     done(null, profile)
 | |
|   })
 | |
| }
 | |
| 
 | |
| passport.use(new OAuth2CustomStrategy({
 | |
|   authorizationURL: config.oauth2.authorizationURL,
 | |
|   tokenURL: config.oauth2.tokenURL,
 | |
|   clientID: config.oauth2.clientID,
 | |
|   clientSecret: config.oauth2.clientSecret,
 | |
|   callbackURL: config.serverURL + '/auth/oauth2/callback',
 | |
|   userProfileURL: config.oauth2.userProfileURL,
 | |
|   scope: config.oauth2.scope
 | |
| }, passportGeneralCallback))
 | |
| 
 | |
| oauth2Auth.get('/auth/oauth2', function (req, res, next) {
 | |
|   passport.authenticate('oauth2')(req, res, next)
 | |
| })
 | |
| 
 | |
| // github auth callback
 | |
| oauth2Auth.get('/auth/oauth2/callback',
 | |
|   passport.authenticate('oauth2', {
 | |
|     successReturnToOrRedirect: config.serverURL + '/',
 | |
|     failureRedirect: config.serverURL + '/'
 | |
|   })
 | |
| )
 |