UNPKG

jive-sdk

Version:

Node.js SDK for Jive Software to assist with the development of add-ons

541 lines (422 loc) 15.5 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Jive SDK Source: jive-sdk-service/routes/oauth.js</title> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/sunlight.default.css"> <link type="text/css" rel="stylesheet" href="styles/site.spacelab.css"> </head> <body> <div class="container-fluid"> <div class="navbar navbar-fixed-top navbar-inverse"> <div class="navbar-inner"> <a class="brand" href="index.html">Jive SDK</a> <ul class="nav"> <li class="dropdown"> <a href="modules.list.html" class="dropdown-toggle" data-toggle="dropdown">Modules<b class="caret"></b></a> <ul class="dropdown-menu "> <li> <a href="module-abstractDefinitions.html">abstractDefinitions</a> </li> <li> <a href="module-abstractInstances.html">abstractInstances</a> </li> <li> <a href="module-addOnRoutes.html">addOnRoutes</a> </li> <li> <a href="module-api.html">api</a> </li> <li> <a href="module-community.html">community</a> </li> <li> <a href="module-constants.html">constants</a> </li> <li> <a href="module-devRoutes.html">devRoutes</a> </li> <li> <a href="module-events.html">events</a> </li> <li> <a href="module-extensions.html">extensions</a> </li> <li> <a href="module-extstreamsInstances.html">extstreamsInstances</a> </li> <li> <a href="module-jiveutil.html">jiveutil</a> </li> <li> <a href="module-oauthRoutes.html">oauthRoutes</a> </li> <li> <a href="module-request.html">request</a> </li> <li> <a href="module-security.html">security</a> </li> <li> <a href="module-service.html">service</a> </li> <li> <a href="module-tasks.html">tasks</a> </li> <li> <a href="module-tileInstances.html">tileInstances</a> </li> <li> <a href="module-tileRoutes.html">tileRoutes</a> </li> <li> <a href="module-tilesDefinitions.html">tilesDefinitions</a> </li> <li> <a href="module-webhooks.html">webhooks</a> </li> </ul> </li> <li class="dropdown"> <a href="classes.list.html" class="dropdown-toggle" data-toggle="dropdown">Classes<b class="caret"></b></a> <ul class="dropdown-menu "> <li> <a href="extstreamsDefinitions.html">extstreamsDefinitions</a> </li> <li> <a href="filePersistence.html">filePersistence</a> </li> <li> <a href="memoryPersistence.html">memoryPersistence</a> </li> <li> <a href="memoryScheduler.html">memoryScheduler</a> </li> <li> <a href="oauthHandler.html">oauthHandler</a> </li> </ul> </li> </ul> </div> </div> <div class="row-fluid"> <div class="span12"> <div id="main"> <h1 class="page-title">Source: jive-sdk-service/routes/oauth.js</h1> <section> <article> <pre class="sunlight-highlight-javascript linenums">/* * Copyright 2013 Jive Software * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @module oauthRoutes */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// var http = require('http'); var url = require('url'); var jive = require('../api'); var mustache = require('mustache'); var q = require('q'); var util = require("util"); exports.redirectHtmlTxt = "&lt;html> &lt;head> &lt;script> window.location='{{{redirect}}}'; &lt;/script>" + "&lt;/head> &lt;body> Redirecting ... &lt;/body> &lt;/html>"; exports.fetchOAuth2Conf = function() { return jive.service.options['oauth2']; }; function getOAuth2Conf(targetJiveTenantID, originJiveTenantID, self) { var deferred = q.defer(); if ( targetJiveTenantID ) { jive.community.findByTenantID(targetJiveTenantID).then( function( community ) { if ( community ) { try{ var oauth2Conf = JSON.parse( JSON.stringify(self.fetchOAuth2Conf( { 'originJiveTenantID' : originJiveTenantID, 'targetJiveTenantID' : targetJiveTenantID }) || {} ) ); } catch ( e ) { deferred.reject(e); return; } oauth2Conf['oauth2ConsumerKey'] = community['clientId']; oauth2Conf['oauth2ConsumerSecret'] = community['clientSecret']; oauth2Conf['originServerAuthorizationUrl'] = community['jiveUrl'] + '/oauth2/authorize'; oauth2Conf['originServerTokenRequestUrl'] = community['jiveUrl'] + '/oauth2/token'; deferred.resolve( oauth2Conf ); } else { deferred.reject(new Error("Could not find community for tenantID " + targetJiveTenantID )); } }); } else { deferred.resolve( self.fetchOAuth2Conf({ 'originJiveTenantID' : originJiveTenantID, 'targetJiveTenantID' : targetJiveTenantID }) ); } return deferred.promise; } /** * &lt;h5>Route:&lt;/h5> * &lt;i>GET /authorizeUrl&lt;/i> * &lt;br>&lt;br> * Expects: * - viewerID * - callback * - base64 encoded Authorization header * @param req * @param res */ exports.authorizeUrl = function(req, res ) { var url_parts = url.parse(req.url, true); var query = url_parts.query; var viewerID = query['viewerID']; var callback = query['callback']; var targetJiveTargetID = query['jiveTenantID']; var jiveExtensionHeaders = jive.util.request.parseJiveExtensionHeaders(req); if (jiveExtensionHeaders ) { var originJiveTenantID = jiveExtensionHeaders['tenantID']; jive.logger.debug('Origin jive tenantID', originJiveTenantID); } var contextStr = query['context']; if ( contextStr ) { try { var context = JSON.parse( decodeURI(contextStr) ); } catch (e) { errorResponse( res, 400, 'Invalid context string, could not parse'); return; } } // encode the target jiveTenantID in the context if ( targetJiveTargetID ) { context = context || {}; context = { 'jiveTenantID' : targetJiveTargetID }; } // encode the origin jiveTenantID in the context if ( originJiveTenantID ) { context = context || {}; context['originJiveTenantID'] = originJiveTenantID; } var extraAuthParamsStr = query['extraAuthParams']; if ( extraAuthParamsStr ) { try { var extraAuthParams = JSON.parse( decodeURI(extraAuthParamsStr )); } catch (e) { errorResponse( res, 400, 'Invalid extra auth param string, could not parse'); return; } } var self = this; getOAuth2Conf(targetJiveTargetID, originJiveTenantID, this ).then( function(oauth2Conf) { jive.logger.info(JSON.stringify(oauth2Conf, null, 4)); var responseMap = self.buildAuthorizeUrlResponseMap( oauth2Conf, callback, { 'viewerID': viewerID, 'context': context}, extraAuthParams ); jive.logger.debug('Sending', responseMap); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end( JSON.stringify(responseMap) ); }, function(err) { errorResponse( res, 404, err); }); }; /** * Override this in a subclass! * @param oauth2CallbackRequest * @param originServerAccessTokenResponse * @param callback */ exports.oauth2SuccessCallback = function( state, originServerAccessTokenResponse, callback ) { jive.logger.debug('State', state); jive.logger.debug('Origin server Access Token Response', originServerAccessTokenResponse); callback(); }; var errorResponse = function( res, code, error ){ res.status(code); res.set({'Content-Type': 'application/json'}); var err = {'error':error}; res.send( JSON.stringify(err) ); jive.logger.debug(err); }; /** * &lt;h4>&lt;i>POST /oauth2Callback&lt;/i>&lt;/h4> * &lt;br> * Expects: * - code * - state, which is a base64 encoded JSON structure containing at minimum jiveRedirectUrl attribute * @param req * @param res */ exports.oauth2Callback = function(req, res ) { var url_parts = url.parse(req.url, true); var query = url_parts.query; var code = query['code']; if ( !code ) { errorResponse( res, 400, 'Authorization code required'); return; } var stateStr = query['state']; if ( !stateStr ) { errorResponse( res, 400, 'Missing state string'); return; } try { var state = JSON.parse( JSON.parse( jive.util.base64Decode(stateStr)) ); } catch ( e ) { errorResponse( res, 400, 'Invalid state string, cannot parse.'); return; } var jiveRedirectUrl = state['jiveRedirectUrl']; if ( !jiveRedirectUrl ) { errorResponse( res, 400, 'Invalid state string, no jiveRedirectUrl provided.'); return; } var jiveTenantID = state['context'] ? state['context']['jiveTenantID'] : undefined; var originJiveTenantID = state['context'] ? state['context']['originJiveTenantID'] : undefined; var self = this; getOAuth2Conf(jiveTenantID, originJiveTenantID, this).then( ///////////// function(oauth2Conf) { var oauth2CallbackExtraParams = oauth2Conf['oauth2CallbackExtraParams']; var postObject = self.buildOauth2CallbackObject( oauth2Conf, code, oauth2CallbackExtraParams ); jive.logger.debug("Post object", postObject); var headers = { 'Content-Type': 'application/x-www-form-urlencoded' }; var proceed = function(context) { var redirectParams = ''; if ( context &amp;&amp; typeof context === 'object' ) { for (var key in context) { if (context.hasOwnProperty(key)) { if (redirectParams.length > 0) { redirectParams += '&amp;'; } redirectParams += encodeURIComponent(key) + '=' + encodeURIComponent(context[key]); } } } var redirect = decodeURIComponent(jiveRedirectUrl) + ( redirectParams ? '?' : '') + redirectParams; var redirectHtml = mustache.render( self.redirectHtmlTxt, { 'redirect' : redirect } ); res.status(200); res.set({'Content-Type': 'text/html'}); res.send(redirectHtml); }; var oauth2SuccessCallback = self.oauth2SuccessCallback; jive.util.buildRequest( oauth2Conf['originServerTokenRequestUrl'], 'POST', postObject, headers).then( function(response) { // success if ( response.statusCode >= 200 &amp;&amp; response.statusCode &lt; 299 ) { if (oauth2SuccessCallback) { oauth2SuccessCallback( state, response, proceed ); } else { proceed(); } } else { res.status(response.statusCode); res.set({'Content-Type': 'application/json'}); res.send(response.entity); } }, function(e) { // failure errorResponse( res, 500, e); } ); }, ///////////// function(err) { errorResponse( res, 500, err); } ); }; exports.buildAuthorizeUrlResponseMap = function (oauth2Conf, callback, context, extraAuthParams) { var stateToEncode = { 'jiveRedirectUrl': callback }; if (context) { stateToEncode = util._extend(stateToEncode, context); } var url = oauth2Conf['originServerAuthorizationUrl'] + "?" + "state=" + jive.util.base64Encode(JSON.stringify(stateToEncode)) + "&amp;redirect_uri=" + oauth2Conf['clientOAuth2CallbackUrl'] + "&amp;client_id=" + oauth2Conf['oauth2ConsumerKey'] + "&amp;response_type=" + "code"; if (extraAuthParams) { var extraAuthStr = ''; for (var key in extraAuthParams) { if (extraAuthParams.hasOwnProperty(key)) { extraAuthStr += '&amp;' + key + '=' + extraAuthParams[key]; } } url += extraAuthStr; } return { 'url': url }; }; exports.buildOauth2CallbackObject = function (oauth2Conf, code, extraParams) { var postObject = { 'grant_type': 'authorization_code', 'redirect_uri': oauth2Conf['clientOAuth2CallbackUrl'], 'client_id': oauth2Conf['oauth2ConsumerKey'], 'client_secret': oauth2Conf['oauth2ConsumerSecret'], 'code': code }; if (extraParams) { postObject = util._extend(postObject, extraParams); } return postObject; }; </pre> </article> </section> </div> <div class="clearfix"></div> <footer> <span class="copyright"> Jive Software, Inc </span> <br /> <span class="jsdoc-message"> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.3.0-dev</a> on Wed Jan 22 2014 12:29:37 GMT-0800 (PST) using the <a href="https://github.com/terryweiss/docstrap">DocStrap template</a>. </span> </footer> </div> <br clear="both"> </div> </div> <script src="scripts/sunlight.js"></script> <script src="scripts/sunlight.javascript.js"></script> <script src="scripts/sunlight-plugin.doclinks.js"></script> <script src="scripts/sunlight-plugin.linenumbers.js"></script> <script src="scripts/sunlight-plugin.menu.js"></script> <script src="scripts/jquery.min.js"></script> <script src="scripts/jquery.scrollTo.js"></script> <script src="scripts/jquery.localScroll.js"></script> <script src="scripts/bootstrap-dropdown.js"></script> <script src="scripts/toc.js"></script> <script> Sunlight.highlightAll({lineNumbers:true, showMenu: true, enableDoclinks :true}); </script> <script> $( function () { $( "#toc" ).toc( { selectors : "h1,h2,h3,h4", showAndHide : false, scrollTo : 60 } ); $( "#toc>ul" ).addClass( "nav nav-pills nav-stacked" ); $( "#main span[id^='toc']" ).addClass( "toc-shim" ); } ); </script> </body> </html>