passport-soundcloud-token
Version:
Passport strategy for authenticating with SoundCloud via OAuth2 access tokens
151 lines (123 loc) • 6.34 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _passportOauth = require('passport-oauth');
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
/**
* `Strategy` constructor.
* The SoundCloud authentication strategy authenticates requests by delegating to SoundCloud using OAuth2 access tokens.
* Applications must supply a `verify` callback which accepts a accessToken, refreshToken, profile and callback.
* Callback supplying a `user`, which should be set to `false` if the credentials are not valid.
* If an exception occurs, `error` should be set.
*
* Options:
* - clientID Identifies client to SoundCloud App
* - clientSecret Secret used to establish ownership of the consumer key
* - passReqToCallback If need, pass req to verify callback
*
* @param {Object} _options
* @param {Function} _verify
* @example
* passport.use(new SoundCloudTokenStrategy({
* clientID: '123456789',
* clientSecret: 'shhh-its-a-secret'
* }), function(req, accessToken, refreshToken, profile, next) {
* User.findOrCreate({soundCloudId: profile.id}, function(error, user) {
* next(error, user);
* })
* })
*/
var SoundCloudTokenStrategy = function (_OAuth2Strategy) {
_inherits(SoundCloudTokenStrategy, _OAuth2Strategy);
function SoundCloudTokenStrategy(_options, _verify) {
_classCallCheck(this, SoundCloudTokenStrategy);
var options = _options || {};
var verify = _verify;
options.authorizationURL = options.authorizationURL || 'https://soundcloud.com/connect';
options.tokenURL = options.tokenURL || 'https://api.soundcloud.com/oauth2/token';
var _this = _possibleConstructorReturn(this, (SoundCloudTokenStrategy.__proto__ || Object.getPrototypeOf(SoundCloudTokenStrategy)).call(this, options, verify));
_this.name = 'soundcloud-token';
_this._accessTokenField = options.accessTokenField || 'access_token';
_this._refreshTokenField = options.refreshTokenField || 'refresh_token';
_this._profileURL = options.profileURL || 'https://api.soundcloud.com/me.json';
_this._passReqToCallback = options.passReqToCallback;
_this._oauth2.setAccessTokenName(options.oauth2AccessTokenName || 'oauth_token');
return _this;
}
/**
* Authenticate method
* @param {Object} req
* @param {Object} options
* @returns {*}
*/
_createClass(SoundCloudTokenStrategy, [{
key: 'authenticate',
value: function authenticate(req, options) {
var _this2 = this;
var accessToken = req.body && req.body[this._accessTokenField] || req.query && req.query[this._accessTokenField];
var refreshToken = req.body && req.body[this._refreshTokenField] || req.query && req.query[this._refreshTokenField];
if (!accessToken) return this.fail({ message: 'You should provide ' + this._accessTokenField });
this._loadUserProfile(accessToken, function (error, profile) {
if (error) return _this2.error(error);
var verified = function verified(error, user, info) {
if (error) return _this2.error(error);
if (!user) return _this2.fail(info);
return _this2.success(user, info);
};
if (_this2._passReqToCallback) {
_this2._verify(req, accessToken, refreshToken, profile, verified);
} else {
_this2._verify(accessToken, refreshToken, profile, verified);
}
});
}
/**
* Parse user profile
* @param {String} accessToken SoundCloud OAuth2 access token
* @param {Function} done
*/
}, {
key: 'userProfile',
value: function userProfile(accessToken, done) {
this._oauth2.get(this._profileURL, accessToken, function (error, body, res) {
if (error) {
try {
var errorJSON = JSON.parse(error.data);
return done(new _passportOauth.InternalOAuthError(errorJSON.errors[0].error_message, error.statusCode));
} catch (_) {
return done(new _passportOauth.InternalOAuthError('Failed to fetch user profile', error));
}
}
try {
var json = JSON.parse(body);
var profile = {
provider: 'soundcloud',
id: json.id,
username: json.username,
displayName: json.full_name || '',
name: {
familyName: json.full_name ? json.full_name.split(' ', 2)[1] : '',
givenName: json.full_name ? json.full_name.split(' ', 2)[0] : ''
},
emails: [],
photos: [{
value: json.avatar_url || ''
}],
_raw: body,
_json: json
};
return done(null, profile);
} catch (e) {
return done(e);
}
});
}
}]);
return SoundCloudTokenStrategy;
}(_passportOauth.OAuth2Strategy);
exports.default = SoundCloudTokenStrategy;
module.exports = exports['default'];