mirror of
https://github.com/hanzoai/passport-discord.git
synced 2026-09-23 23:46:59 +00:00
First commit - working passport oauth
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
npm-debug.log*
|
||||
@@ -0,0 +1,49 @@
|
||||
# passport-discord
|
||||
|
||||
Passport strategy for authentication with [Discord](http://discordapp.com) through the OAuth 2.0 API.
|
||||
|
||||
At time of writing there is no official page/documentation for this, so information can be read off the example project, such as how to set up an API application [here](http://github.com/vishnevskiy/discord-oauth2-example).
|
||||
|
||||
## Usage
|
||||
`npm install passport-discord --save`
|
||||
|
||||
#### Configure Strategy
|
||||
The Discord authentication strategy authenticates users via a Discord user account and OAuth 2.0 token(s). A Discord API client ID, secret and redirect URL must be supplied when using this strategy. The strategy also requires a `verify` callback, which receives the access token and an optional refresh token, as well as a `profile` which contains the authenticated Discord user's profile. The `verify` callback must also call `cb` providing a user to complete the authentication.
|
||||
|
||||
```javascript
|
||||
var DiscordStrategy = require('passport-discord').Strategy;
|
||||
|
||||
passport.use(new DiscordStrategy(
|
||||
{
|
||||
clientID: 'id',
|
||||
clientSecret: 'secret',
|
||||
callbackURL: 'callbackURL'
|
||||
},
|
||||
function(accessToken, refreshToken, profile, cb) {
|
||||
User.findOrCreate({ discordId: profile.id }, function(err, user) {
|
||||
return cb(err, user);
|
||||
});
|
||||
}
|
||||
));
|
||||
```
|
||||
|
||||
#### Authentication Requests
|
||||
Use `passport.authenticate()`, and specify the `'discord'` strategy to authenticate requests.
|
||||
|
||||
Foe example, as a route middleware in an Express app:
|
||||
|
||||
```javascript
|
||||
app.get('/auth/discord', passport.authenticate('discord'));
|
||||
app.get('/auth/discord/callback', passport.authenticate('discord', {
|
||||
failureRedirect: '/'
|
||||
}), function(req, res) {
|
||||
res.redirect('/secretstuff') // Successful auth
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## Examples
|
||||
An Express server example can be found in the `/example` directory. Be sure to `npm install` in that directory to get the dependencies.
|
||||
|
||||
## Credits
|
||||
* Jared Hanson - used passport-github to understand passport more and kind of as a base.
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "passport-discord-example",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "node server.js"
|
||||
},
|
||||
"author": "Nicholas Tay <[email protected]> (http://nicholastay.github.io)",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"express": "^4.13.4",
|
||||
"express-session": "^1.13.0",
|
||||
"passport": "^0.3.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
var express = require('express')
|
||||
, session = require('express-session')
|
||||
, passport = require('passport')
|
||||
, Strategy = require('../lib').Strategy
|
||||
, app = express();
|
||||
|
||||
passport.serializeUser(function(user, done) {
|
||||
done(null, user);
|
||||
});
|
||||
passport.deserializeUser(function(obj, done) {
|
||||
done(null, obj);
|
||||
});
|
||||
|
||||
var scopes = ['identify', 'email', /* 'connections', (it is currently broken) */ 'guilds', 'guilds.join'];
|
||||
|
||||
passport.use(new Strategy({
|
||||
clientID: '',
|
||||
clientSecret: '',
|
||||
callbackURL: 'http://localhost:5000/callback',
|
||||
scope: scopes
|
||||
}, function(accessToken, refreshToken, profile, done) {
|
||||
process.nextTick(function() {
|
||||
return done(null, profile);
|
||||
});
|
||||
}));
|
||||
|
||||
app.use(session({
|
||||
secret: 'keyboard cat',
|
||||
resave: false,
|
||||
saveUninitialized: false
|
||||
}));
|
||||
app.use(passport.initialize());
|
||||
app.use(passport.session());
|
||||
app.get('/', passport.authenticate('discord', { scope: scopes }), function(req, res) {});
|
||||
app.get('/callback',
|
||||
passport.authenticate('discord', { failureRedirect: '/' }), function(req, res) { res.redirect('/info') } // auth success
|
||||
);
|
||||
app.get('/logout', function(req, res) {
|
||||
req.logout();
|
||||
res.redirect('/');
|
||||
});
|
||||
app.get('/info', checkAuth, function(req, res) {
|
||||
//console.log(req.user)
|
||||
res.json(req.user);
|
||||
});
|
||||
|
||||
|
||||
function checkAuth(req, res, next) {
|
||||
if (req.isAuthenticated()) return next();
|
||||
res.send('not logged in :(');
|
||||
}
|
||||
|
||||
|
||||
app.listen(5000, function (err) {
|
||||
if (err) return console.log(err)
|
||||
console.log('Listening at http://localhost:5000/')
|
||||
})
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
var Strategy = require('./strategy');
|
||||
|
||||
/**
|
||||
* Expose `Strategy` directly from package.
|
||||
*/
|
||||
exports = module.exports = Strategy;
|
||||
|
||||
/**
|
||||
* Export constructors.
|
||||
*/
|
||||
exports.Strategy = Strategy;
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* Dependencies
|
||||
*/
|
||||
var OAuth2Strategy = require('passport-oauth2')
|
||||
, InternalOAuthError = require('passport-oauth2').InternalOAuthError
|
||||
, util = require('util');
|
||||
|
||||
/**
|
||||
* `Strategy` constructor.
|
||||
*
|
||||
* The Discord authentication strategy authenticates requests by delegating to
|
||||
* Discord via the OAuth2.0 protocol
|
||||
*
|
||||
* Applications must supply a `verify` callback which accepts an `accessToken`,
|
||||
* `refreshToken` and service-specific `profile`, and then calls the `cb`
|
||||
* callback supplying a `user`, which should be set to `false` if the
|
||||
* credentials are not valid. If an exception occured, `err` should be set.
|
||||
*
|
||||
* Options:
|
||||
* - `clientID` OAuth ID to discord
|
||||
* - `clientSecret` OAuth Secret to verify client to discord
|
||||
* - `callbackURL` URL that discord will redirect to after auth
|
||||
* - `scope` Array of permission scopes to request
|
||||
* Valid discord scopes include: 'identity', 'email', 'connections', 'guilds', 'guilds.join'
|
||||
*
|
||||
* @constructor
|
||||
* @param {object} options
|
||||
* @param {function} verify
|
||||
* @access public
|
||||
*/
|
||||
function Strategy(options, verify) {
|
||||
options = options || {};
|
||||
options.authorizationURL = options.authorizationURL || 'https://discordapp.com/api/oauth2/authorize';
|
||||
options.tokenURL = options.tokenURL || 'https://discordapp.com/api/oauth2/token';
|
||||
options.scopeSeparator = options.scopeSeparator || ' ';
|
||||
|
||||
OAuth2Strategy.call(this, options, verify);
|
||||
this.name = 'discord';
|
||||
this._oauth2.useAuthorizationHeaderforGET(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inherits from `OAuth2Strategy`
|
||||
*/
|
||||
util.inherits(Strategy, OAuth2Strategy);
|
||||
|
||||
/**
|
||||
* Retrieve user profile from Discord.
|
||||
*
|
||||
* This function constructs a normalized profile, with the following properties:
|
||||
*
|
||||
* - `something` ayy lmao
|
||||
*
|
||||
* @param {string} accessToken
|
||||
* @param {function} done
|
||||
* @access protected
|
||||
*/
|
||||
Strategy.prototype.userProfile = function(accessToken, done) {
|
||||
var self = this;
|
||||
this._oauth2.get('https://discordapp.com/api/users/@me', accessToken, function(err, body, res) {
|
||||
if (err) {
|
||||
return done(new InternalOAuthError('Failed to fetch the user profile.', err))
|
||||
}
|
||||
|
||||
try {
|
||||
var parsedData = JSON.parse(body);
|
||||
}
|
||||
catch (e) {
|
||||
return done(new Error('Failed to parse the user profile.'));
|
||||
}
|
||||
|
||||
var profile = parsedData; // has the basic user stuff
|
||||
profile.provider = 'discord';
|
||||
|
||||
self.checkScope('connections', accessToken, function(errx, connections) {
|
||||
if (errx) done(errx);
|
||||
if (connections) profile.connections = connections;
|
||||
self.checkScope('guilds', accessToken, function(erry, guilds) {
|
||||
if (erry) done(erry);
|
||||
if (guilds) profile.guilds = guilds;
|
||||
|
||||
return done(null, profile)
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Strategy.prototype.checkScope = function(scope, accessToken, cb) {
|
||||
if (this._scope && this._scope.indexOf(scope) !== -1) {
|
||||
this._oauth2.get('https://discordapp.com/api/users/@me/' + scope, accessToken, function(err, body, res) {
|
||||
if (err) return cb(new InternalOAuthError('Failed to fetch user\'s ' + scope, err));
|
||||
try {
|
||||
var json = JSON.parse(body);
|
||||
}
|
||||
catch (e) {
|
||||
return cb(new Error('Failed to parse user\'s ' + scope));
|
||||
}
|
||||
cb(null, json);
|
||||
});
|
||||
} else {
|
||||
cb(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Expose `Strategy`.
|
||||
*/
|
||||
module.exports = Strategy;
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "passport-discord",
|
||||
"version": "0.1.0",
|
||||
"description": "Passport strategy for authentication with Discord (discordapp.com)",
|
||||
"main": "lib/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/nicholastay/passport-discord.git"
|
||||
},
|
||||
"keywords": [
|
||||
"passport",
|
||||
"discord",
|
||||
"auth",
|
||||
"authentication",
|
||||
"authn",
|
||||
"identity"
|
||||
],
|
||||
"author": "Nicholas Tay <[email protected]> (http://nicholastay.github.io)",
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/nicholastay/passport-discord/issues"
|
||||
},
|
||||
"homepage": "https://github.com/nicholastay/passport-discord#readme",
|
||||
"dependencies": {
|
||||
"passport-oauth2": "^1.2.0"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user