├── .gitignore ├── example ├── views │ ├── intro.jade │ ├── layout.jade │ ├── error.jade │ ├── ready.jade │ ├── ok.jade │ └── home.jade ├── settings_example.json ├── package.json ├── Readme.md ├── index.js └── public │ └── main.css ├── default.json ├── package.json ├── Readme.md ├── LICENSE ├── History.md └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | example/settings.json 3 | -------------------------------------------------------------------------------- /example/views/intro.jade: -------------------------------------------------------------------------------- 1 | p 2 | | Simple application to test 3 | a(href="https://www.github.com/cloudup/wp-oauth") wpcom-oauth 4 | | module. 5 | -------------------------------------------------------------------------------- /example/views/layout.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title WPOAuth 5 | link(rel="stylesheet", href="/main.css") 6 | 7 | body 8 | h1 WPOAuth 9 | block content 10 | -------------------------------------------------------------------------------- /example/settings_example.json: -------------------------------------------------------------------------------- 1 | { 2 | "client_id": "", 3 | "client_secret": "", 4 | "url": { 5 | "redirect": "http://localhost:3001/connect/res" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /example/views/error.jade: -------------------------------------------------------------------------------- 1 | 2 | extends layout 3 | 4 | block content 5 | include intro 6 | h2.err Error 7 | table.err 8 | tr 9 | td error 10 | td #{error} 11 | tr 12 | td description 13 | td #{error_description} 14 | p.msg 15 | a(href='/') Try again ? 16 | -------------------------------------------------------------------------------- /example/views/ready.jade: -------------------------------------------------------------------------------- 1 | 2 | extends layout 3 | 4 | block content 5 | include intro 6 | 7 | h2 Ready to request the access token 8 | p The code gotten is #{code}. This code allow us get for the access token. 9 | 10 | p.msg 11 | a(href='/get_token/' + code) Let's get it! 12 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "name": "wp-oauth-testing-app", 4 | "description": "A application to test the wp-oauth", 5 | "version": "0.0.1", 6 | "author": { 7 | "name": "Damian Suarez", 8 | "email": "rdsuarez@gmail.com" 9 | }, 10 | "main": "./index.js", 11 | "dependencies": { 12 | "express": "3.5.0", 13 | "jade": "1.3.0" 14 | }, 15 | "devDependencies": { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /default.json: -------------------------------------------------------------------------------- 1 | { 2 | "response_type": "code", 3 | "url": { 4 | "redirect": "/wpoauth/connected" 5 | }, 6 | "endpoint": { 7 | "request_token": "https://public-api.wordpress.com/oauth2/token", 8 | "authorize": "https://public-api.wordpress.com/oauth2/authorize", 9 | "authenticate": "https://public-api.wordpress.com/oauth2/authenticate" 10 | }, 11 | "grant_type": "authorization_code" 12 | } 13 | -------------------------------------------------------------------------------- /example/views/ok.jade: -------------------------------------------------------------------------------- 1 | 2 | extends layout 3 | 4 | block content 5 | include intro 6 | 7 | h2.ok Request has been successful 8 | table.ok 9 | tr 10 | td access_token 11 | td.access_token #{access_token} 12 | tr 13 | td token_type 14 | td #{token_type} 15 | tr 16 | td blog_id 17 | td #{blog_id} 18 | tr 19 | td blog_url 20 | td #{blog_url} 21 | tr 22 | td scope 23 | td #{scope} 24 | p.msg 25 | a(href='/') Try again ? 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wpcom-oauth", 3 | "description": "WordPress.com OAuth2 authorization module for Node.js", 4 | "version": "0.3.4", 5 | "author": "Automattic, Inc.", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/Automattic/node-wpcom-oauth.git" 9 | }, 10 | "contributors": [ 11 | "Damian Suarez ", 12 | "Nathan Rajlich ", 13 | "Ben Lowery " 14 | ], 15 | "main": "./index.js", 16 | "license": "MIT", 17 | "dependencies": { 18 | "debug": "*", 19 | "superagent": "^3.8.3" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example/views/home.jade: -------------------------------------------------------------------------------- 1 | 2 | extends layout 3 | 4 | block content 5 | include intro 6 | 7 | h2 Settings 8 | table 9 | tr 10 | td your client id 11 | td #{settings.client_id} 12 | tr 13 | td your client secret 14 | td.client_secret #{settings.client_secret} 15 | tr 16 | td redirect url 17 | td.client_secret #{settings.url.redirect} 18 | p Settings are defined in settings.json file. 19 | 20 | h2 Get the code 21 | p Use WPOAuth#urlToConnect() method to get the url to get for the code. 22 | 23 | table 24 | tr 25 | td url 26 | td.url #{url} 27 | p.msg 28 | a(href=url) Let's get the code ! 29 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | [![npm version](https://badge.fury.io/js/wpcom-oauth.svg)](https://badge.fury.io/js/wpcom-oauth) 2 | 3 | # wpcom-oauth 4 | 5 | [WordPress.com](http://wordpress.com) OAuth2 **server-side** authorization module for 6 | [Node.js](http://www.nodejs.org). 7 | 8 | The **client-side** counterpart to this module is 9 | [`wpcom-oauth-cors`](https://github.com/Automattic/wpcom-oauth-cors). 10 | 11 | ## Installation 12 | 13 | ```bash 14 | $ npm install wpcom-oauth 15 | ``` 16 | 17 | ## API 18 | 19 | ### WPOAuth#urlToConnect(resource) 20 | 21 | Return the url that points to first step for get the access token. 22 | 23 | ### WPOAuth#code(code) 24 | 25 | Set the code to request the access token. 26 | 27 | ### WPOAuth#requestAccessToken(fn) 28 | 29 | Start the OAuth2 request to WordPress.com and execute the callback function when it's done. 30 | 31 | ## Simple example application 32 | 33 | See the [example documentation](./example/Readme.md) to run the app 34 | 35 | ## License 36 | 37 | MIT – Copyright 2014 Automattic 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2014 Automattic, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the "Software"), to deal in the Software without 8 | restriction, including without limitation the rights to use, 9 | copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /example/Readme.md: -------------------------------------------------------------------------------- 1 | 2 | # Simple WPOAuth application 3 | 4 | Simple application to show how WPAuth works. 5 | 6 | ## How to use 7 | 8 | ### 1 - Create a WordPress application 9 | 10 | Go to [wordpress apps](https://developer.wordpress.com/apps) and 11 | create your application to use to get the oauth access token. 12 | 13 | ### 2 - Create a settings file 14 | 15 | In the `example/` folder copy `settings_example.json` to `settings.json` and 16 | customize as needed. Your `settings.json` file should look something like 17 | this: 18 | 19 | ```json 20 | { 21 | "client_id": "", 22 | "client_secret": "", 23 | "url": { 24 | "redirect": "http://localhost:3001/connect/res" 25 | } 26 | } 27 | ``` 28 | 29 | Other settings that you can change, if needed: 30 | 31 | - `port` - if you need to change the default port to something else. Don't 32 | forget to update your `url.redirect` setting too. 33 | 34 | ### 3 - Update dependencies 35 | 36 | From the `example/` folder, download and install the npm dependencies: 37 | 38 | ```cli 39 | $ npm install 40 | ``` 41 | 42 | ### 4 - Run the application 43 | 44 | ```cli 45 | $ node index.js 46 | ``` 47 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Module dependencies. 4 | */ 5 | 6 | var URL = require('url'); 7 | var express = require('express'); 8 | var WPOAuth = require('../'); 9 | 10 | /** 11 | * Get settings data 12 | */ 13 | 14 | var settings = require('./settings.json'); 15 | 16 | /** 17 | * Create a WPOAuth instance 18 | */ 19 | 20 | var wpoauth = WPOAuth(settings); 21 | 22 | var pub = __dirname + '/public'; 23 | var app = express(); 24 | app.use(express.static(pub)); 25 | 26 | app.set('views', __dirname + '/views'); 27 | app.set('view engine', 'jade'); 28 | 29 | // homepage route 30 | app.get('/', function(req, res){ 31 | res.render('home', { 32 | settings: settings, 33 | url: wpoauth.urlToConnect() 34 | }); 35 | }); 36 | 37 | var redirectPath = URL.parse(wpoauth.opts.url.redirect).pathname; 38 | 39 | // connect response route 40 | // grab code query param 41 | app.get(redirectPath, function(req, res){ 42 | var code = req.query.code; 43 | res.render('ready', { code: code }); 44 | }); 45 | 46 | // access token route 47 | app.get('/get_token/:code', function(req, res){ 48 | // pass the code into settings parameters 49 | wpoauth.code(req.params.code); 50 | 51 | // request access token 52 | wpoauth.requestAccessToken(function(err, data){ 53 | if (err) return res.render('error', err); 54 | res.render('ok', data); 55 | }); 56 | }); 57 | 58 | var port = settings.port || 3001; 59 | app.listen(port); 60 | console.log('WPOAuth app started on port %d', port); 61 | -------------------------------------------------------------------------------- /example/public/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font: 14px "Helvetica Nueue", "Lucida Grande", Arial, sans-serif; 3 | padding: 50px 80px; 4 | margin: 0; 5 | } 6 | 7 | h1 { 8 | color: #a04; 9 | } 10 | 11 | h2 { 12 | margin-top: 50px; 13 | } 14 | 15 | h2.err { 16 | background-color: #fee; 17 | color: red; 18 | padding: 5px 20px; 19 | } 20 | 21 | h2.ok { 22 | background-color: #efe; 23 | color: #080; 24 | padding: 5px 20px; 25 | } 26 | 27 | table { 28 | border-spacing: 0; 29 | } 30 | 31 | table tr td { 32 | padding: 5px 15px; 33 | border-bottom: 2px solid white 34 | } 35 | 36 | table tr td:nth-child(1) { 37 | background-color: #eee; 38 | font-size: 12px; 39 | color: #aaa; 40 | } 41 | 42 | table tr td:nth-child(2) { 43 | background-color: #f5f5f5; 44 | color: #448; 45 | } 46 | 47 | table.err tr td:nth-child(2) { 48 | color: #a04; 49 | } 50 | 51 | table.ok tr td:nth-child(2) { 52 | color: #082; 53 | } 54 | 55 | em { 56 | padding: 3px 5px; 57 | color: #666; 58 | background-color: #f5f5f5; 59 | border-radius: 2px; 60 | font-style: normal; 61 | } 62 | 63 | .access_token, 64 | .url, 65 | .client_secret { 66 | font-size: 12px; 67 | } 68 | 69 | p.msg { 70 | margin-top: 50px; 71 | text-align: center; 72 | background-color: #eee; 73 | padding: 5px; 74 | } 75 | 76 | p.msg a { 77 | text-decoration: none; 78 | text-transform: uppercase; 79 | font-size: 12px; 80 | font-weight: bold; 81 | color: #004; 82 | text-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); 83 | } 84 | 85 | p.msg a:hover { 86 | color: #00a; 87 | text-decoration: underline; 88 | } 89 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | 2 | 0.3.4 / 2018-06-05 3 | ================== 4 | 5 | * Upgrade superagent dependency to ^3.8 to avoid security issues in qs 6 | 7 | 0.3.3 / 2015-04-09 8 | ================== 9 | 10 | * Final fixes to package names and docs crosslink 11 | * Revert "Fix npm package name" 12 | * Link to client-side module from server-side module docs 13 | * Fix package name in readme 14 | * Fix package name in package.json 15 | 16 | 0.3.2 / 2014-08-01 17 | ================== 18 | 19 | * package: adjust "repository" field 20 | * package: add Nathan Rajlich to "contributors" list 21 | * package: update "description" 22 | * package: add "license" field 23 | * Remove the example test site. If you're not a user of that blog, the authorization will fail. (#6, @mdawaffe) 24 | * Don't hardcode the clien't redirect URL. Instead grab it from the oAuth settings. (#5, @mdawaffe) 25 | * Readme: update title 26 | * Readme: update description 27 | * add LICENSE file 28 | 29 | 0.3.1 / 2014-06-06 30 | ================== 31 | 32 | * add repository name 33 | * 'grant_type' as 'authorization_code' by default 34 | * setCode() by code() 35 | 36 | 0.1.1 / 2014-04-16 37 | ================== 38 | 39 | * add `params` object param to urlToConnect() method 40 | 41 | 0.1.0 / 2014-04-11 42 | ================== 43 | 44 | * rename npm name to `wpcom-oauth` 45 | 46 | 0.0.3 / 2014-03-31 47 | ================== 48 | 49 | * replace `request` by `superagent` 50 | 51 | 0.0.2 / 2014-03-31 52 | ================== 53 | 54 | * add documentation 55 | * add simple express example 56 | * first approach 57 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Module dependencies. 4 | */ 5 | 6 | var req = require('superagent'); 7 | var qs = require('querystring'); 8 | var debug = require('debug')('wpcom-oauth'); 9 | 10 | /** 11 | * Default options 12 | */ 13 | 14 | var def = require('./default.json'); 15 | 16 | /** 17 | * Options 18 | */ 19 | 20 | var globals; 21 | 22 | /** 23 | * Class constructor 24 | * 25 | * @param {Object} options 26 | * @api public 27 | */ 28 | 29 | function WPOAuth(options){ 30 | if (!(this instanceof WPOAuth)) return new WPOAuth(options); 31 | 32 | // Options 33 | this.opts = globals = options || {}; 34 | for (var attr in def){ 35 | this.opts[attr] = this.opts[attr] || def[attr]; 36 | } 37 | 38 | this._code = this.opts.code; 39 | 40 | // Error exceptions 41 | if (!this.opts.client_id) { 42 | throw new Error('`client_id` is required'); 43 | } 44 | 45 | if (!this.opts.client_secret) { 46 | throw new Error('`client_secret` is required'); 47 | } 48 | } 49 | 50 | /** 51 | * Get url to connect 52 | * 53 | * @param {Object} [resource] 54 | * @param {Object} [param] query string vars 55 | * @api public 56 | */ 57 | 58 | WPOAuth.prototype.urlToConnect = function(resource, params){ 59 | return WPOAuth.urlToConnect(resource, params); 60 | }; 61 | 62 | /** 63 | * Set code to build the request for the oauth 64 | * 65 | * @param {String} code 66 | * @api public 67 | */ 68 | 69 | WPOAuth.prototype.code = function(code){ 70 | this._code = code; 71 | debug('code: `%s`', this._code); 72 | }; 73 | 74 | /** 75 | * Send request for token 76 | * 77 | * @param {Function} fn callback 78 | * @api public 79 | */ 80 | 81 | WPOAuth.prototype.requestAccessToken = function(fn){ 82 | if ('undefined' == typeof this._code) { 83 | return fn(new Error('`code` is really needed')); 84 | } 85 | 86 | var data = { 87 | "client_id": this.opts.client_id, 88 | "client_secret": this.opts.client_secret, 89 | "redirect_uri": this.opts.url.redirect, 90 | "code": this._code, 91 | "grant_type": this.opts.grant_type 92 | }; 93 | 94 | var url = this.opts.endpoint.request_token; 95 | 96 | req 97 | .post(url) 98 | .type('form') 99 | .send(data) 100 | .end(function (err, res) { 101 | if (err) return fn(err); 102 | 103 | // api error response 104 | if (res.body && res.body.error) { 105 | return fn(res.body); 106 | } 107 | 108 | fn(null, res.body); 109 | }); 110 | }; 111 | 112 | /** 113 | * Statics 114 | */ 115 | 116 | /** 117 | * Return URL to connect 118 | * 119 | * @param {String} [resource] 120 | * @param {Object} [param] query string vars 121 | * @return {String} url link 122 | * @api public 123 | */ 124 | 125 | WPOAuth.urlToConnect = function(resource, params){ 126 | if ('object' == typeof resource) { 127 | params = resource; 128 | resource = null; 129 | } 130 | params = params || {}; 131 | 132 | params.response_type = globals.response_type; 133 | params.client_id = globals.client_id; 134 | params.redirect_uri = globals.url.redirect; 135 | 136 | if (resource && !params.blog) { 137 | debug('get url: %s', resource); 138 | params.blog = resource; 139 | } 140 | 141 | var link = def.endpoint.authorize + '?' + qs.stringify(params); 142 | debug('url: `%s`', link); 143 | return link; 144 | }; 145 | 146 | /** 147 | * expose `WPOAuth` 148 | */ 149 | 150 | module.exports = WPOAuth; 151 | --------------------------------------------------------------------------------