Create a custom provider
See original GitHub issueHi, I want to create a Twitch login but i can’t make it works …
This is my custom oauth for twitch
/**
* Module dependencies.
*/
const util = require('util');
const OAuth2Strategy = require('passport-oauth2');
const { InternalOAuthError } = require('passport-oauth2');
/**
* `Strategy` constructor.
*
* The Twitch authentication strategy authenticates requests by delegating to
* Twitch using the OAuth 2.0 protocol.
*
* Applications must supply a `verify` callback which accepts an `accessToken`,
* `refreshToken` and service-specific `profile`, and then calls the `done`
* 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` your Twitch application"s client id
* - `clientSecret` your Twitch application"s client secret
* - `callbackURL` URL to which Twitch will redirect the user after granting authorization
*
* Examples:
*
* passport.use(new TwitchStrategy({
* clientID: "123-456-789",
* clientSecret: "shhh-its-a-secret"
* callbackURL: "https://www.example.net/auth/twitch/callback"
* },
* function(accessToken, refreshToken, profile, done) {
* User.findOrCreate(..., function (err, user) {
* done(err, user);
* });
* }
* ));
*
* @param {Object} options
* @param {Function} verify
* @api public
*/
function Strategy(options, verify) {
options = options || {};
options.authorizationURL = options.authorizationURL || 'https://id.twitch.tv/oauth2/authorize';
options.tokenURL = options.tokenURL || 'https://id.twitch.tv/oauth2/token';
OAuth2Strategy.call(this, options, verify);
this.name = 'twitch';
this._oauth2.setAuthMethod('Bearer');
this._oauth2.useAuthorizationHeaderforGET(true);
}
/**
* Inherit from `OAuth2Strategy`.
*/
util.inherits(Strategy, OAuth2Strategy);
/**
* Retrieve user profile from Twitch.
*
* This function constructs a normalized profile, with the following properties:
*
* - `provider` always set to `twitch`
* - `id`
* - `username`
* - `displayName`
*
* @param {String} accessToken
* @param {Function} done
* @api protected
*/
// eslint-disable-next-line func-names
Strategy.prototype.userProfile = function (accessToken, done) {
this._oauth2.get('https://api.twitch.tv/helix/users', accessToken, (err, body, res) => {
if (err) { return done(new InternalOAuthError('failed to fetch user profile', err)); }
try {
const json = JSON.parse(body);
const profile = { provider: 'twitch' };
profile.id = json.data[0].id;
profile.userName = json.data[0].login;
profile.email = json.data[0].email;
profile.displayName = json.data[0].display_name;
profile.profileImageUrl = json.data[0].profile_image_url;
profile.viewCount = json.data[0].view_count;
profile._raw = body;
profile._json = json;
done(null, profile);
} catch (e) {
done(e);
}
});
};
/**
* Return extra parameters to be included in the authorization request.
*
* @param {Object} options
* @return {Object}
* @api protected
*/
// eslint-disable-next-line func-names
Strategy.prototype.authorizationParams = function (options) {
const params = {};
if (typeof options.forceVerify !== 'undefined') {
params.force_verify = !!options.forceVerify;
}
return params;
};
/**
* Expose `Strategy`.
*/
module.exports = Strategy;
I import this custom oauth and create a passport strategy with in passport.js
/**
* Twitch API OAuth.
*/
passport.use(new Strategy({
clientID: process.env.TWITCH_CLIENT_ID,
clientSecret: process.env.TWITCH_CLIENT_SECRET,
callbackURL: `${process.env.BASE_URL}/auth/twitch/callback`,
scope: ['user_read', 'chat:read', 'chat:edit', 'whispers:read', 'whispers:edit', 'user:read:email'],
passReqToCallback: true
},
(req, accessToken, refreshToken, params, profile, done) => {
console.log({ accessToken, refreshToken, params, profile });
if (req.user) {
User.findOne({ twitch: profile.id }, (err, existingUser) => {
if (existingUser) {
req.flash('errors', { msg: 'There is already a Twitch account that belongs to you. Sign in with that account or delete it, then link it with your current account.' });
done(err);
} else {
User.findById(req.user.id, (err, user) => {
if (err) { return done(err); }
user.twitch = profile.id;
user.email = profile.email;
user.tokens.push({
kind: 'twitch',
accessToken,
refreshToken,
accessTokenExpires: moment().add(params.expires_in, 'seconds').format()
});
user.profile.name = user.profile.name || profile.userName || profile.displayName;
user.profile.picture = user.profile.picture || profile.profileImageUrl;
user.save((err) => {
req.flash('info', { msg: 'Twitch account has been linked.' });
done(err, user);
});
});
}
});
} else {
User.findOne({ twitch: profile.id }, (err, existingUser) => {
if (err) { return done(err); }
if (existingUser) {
return done(null, existingUser);
}
User.findOne({ email: profile.email }, (err, existingEmailUser) => {
if (err) { return done(err); }
if (existingEmailUser) {
req.flash('errors', { msg: 'There is already an account using this email address. Sign in to that account and link it with GitHub manually from Account Settings.' });
done(err);
} else {
const user = new User();
user.twitch = profile.id;
user.email = profile.email;
user.tokens.push({
kind: 'twitch',
accessToken,
refreshToken,
accessTokenExpires: moment().add(params.expires_in, 'seconds').format()
});
user.profile.name = user.profile.name || profile.userName || profile.displayName;
user.profile.picture = user.profile.picture || profile.profileImageUrl;
user.save((err) => {
done(err, user);
});
}
});
});
}
}));
I add some links in app.js
/**
* OAuth authorization routes. (API examples)
*/
app.get('/auth/twitch', passport.authorize('twitch', {}));
app.get('/auth/twitch/callback', passport.authorize('twitch', { failureRedirect: '/login' }), (req, res) => {
res.redirect(req.session.returnTo);
});
I add this in login.pug
.offset-md-3.col-md-7.pl-2
a.btn.btn-block.btn-snapchat.btn-social(href='/auth/twitch')
i.fab.fa-snapchat-ghost.fa-sm
| Sign in with Twitch
Everything is OK, i can login, everything is in database but i never got a session ! If i create an account with email it works correctly …
What i have missed ?
Issue Analytics
- State:
- Created 4 years ago
- Comments:6
Top Results From Across the Web
Setup and Implement Read | Terraform - HashiCorp Developer
In these tutorials, you will write a custom provider against the API of a fictional coffee-shop application called HashiCups using the Terraform Plugin ......
Read more >Create and use a custom resource provider - Azure
This tutorial shows how to create and use an Azure Custom Resource Provider. Use custom resource providers to change workflows on Azure.
Read more >How to Develop a Custom Provider in Terraform - InfraCloud
Saravanan explores Terraform Custom Provider - what it is and steps to create and build an example Terraform provider. Let's dive in.
Read more >Writing A Custom Terraform Provider - BoxBoat
The Provider must know the address of the API to communicate with it · The Provider must know how to map specific keywords...
Read more >Custom Terraform Provider Design: Part 01 | by Sourav Patnaik
This is the Part 01 of creating a Custom Terraform Provider to manage our application. Terraform is an Open-Source Infrastructure as Code (IaC)...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
In case if you are still working on this, I added twitch support with https://github.com/sahat/hackathon-starter/commit/c8df1150075b6e32129a9974975529e2e7a2dc37 and https://github.com/sahat/hackathon-starter/commit/901140f3b8949ea79029bab1cf1bf706e8ef2a7c
i got it …
in app.js
should be