UNPKG

passport-soundcloud-token

Version:

Passport strategy for authenticating with SoundCloud via OAuth2 access tokens

151 lines (123 loc) 6.34 kB
'use strict'; 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'];