index.js |
|
---|---|
var ohauth = require('ohauth'),
store = require('store');
|
|
osm-authThis code is only compatible with IE10+ because the XDomainRequest object, IE<10's idea of CORS, does not support custom headers, which this uses everywhere. |
module.exports = function(o) {
var oauth = {};
|
o is for options. for example,
|
o.url = o.url || 'http://www.openstreetmap.org';
|
Optional loading and loading-done functions for nice UI feedback. by default, no-ops |
o.loading = o.loading || function() {};
o.done = o.done || function() {};
|
authenticated users will also have a request token secret, but it's not used in transactions with the server |
oauth.authenticated = function() {
return token('oauth_token') && token('oauth_token_secret');
};
oauth.logout = function() {
token('oauth_token', '');
token('oauth_token_secret', '');
token('oauth_request_token_secret', '');
return oauth;
};
|
TODO: detect lack of click event |
oauth.authenticate = function(callback) {
if (oauth.authenticated()) return callback();
oauth.logout();
|
Getting a request token |
var params = timenonce(getAuth(o)),
url = o.url + '/oauth/request_token';
params.oauth_signature = ohauth.signature(
o.oauth_secret, '',
ohauth.baseString('POST', url, params));
|
Create a 600x550 popup window in the center of the screen |
var w = 600, h = 550,
settings = [
['width', w], ['height', h],
['left', screen.width / 2 - w / 2],
['top', screen.height / 2 - h / 2]].map(function(x) {
return x.join('=');
}).join(','),
popup = window.open('about:blank', 'oauth_window', settings);
|
Request a request token. When this is complete, the popup window is redirected to OSM's authorization page. |
ohauth.xhr('POST', url, params, null, {}, reqTokenDone);
o.loading();
function reqTokenDone(err, xhr) {
o.done();
if (err) return callback(err);
var resp = ohauth.stringQs(xhr.response);
token('oauth_request_token_secret', resp.oauth_token_secret);
popup.location = o.url + '/oauth/authorize?' + ohauth.qsString({
oauth_token: resp.oauth_token,
oauth_callback: location.href.replace('index.html', '')
.replace(/#.+/, '') + 'land.html'
});
}
|
Called by a function in |
window.authComplete = function(token) {
var oauth_token = ohauth.stringQs(token.split('?')[1]);
get_access_token(oauth_token.oauth_token);
delete window.authComplete;
};
|
Getting an request tokenAt this point we have an |
function get_access_token(oauth_token) {
var url = o.url + '/oauth/access_token',
params = timenonce(getAuth(o)),
request_token_secret = token('oauth_request_token_secret');
params.oauth_token = oauth_token;
params.oauth_signature = ohauth.signature(
o.oauth_secret,
request_token_secret,
ohauth.baseString('POST', url, params));
|
Getting an access tokenThe final token required for authentication. At this point
we have a |
ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
o.loading();
}
function accessTokenDone(err, xhr) {
o.done();
if (err) return callback(err);
var access_token = ohauth.stringQs(xhr.response);
token('oauth_token', access_token.oauth_token);
token('oauth_token_secret', access_token.oauth_token_secret);
callback(null, oauth);
}
};
|
xhrA single XMLHttpRequest wrapper that does authenticated calls if the user has logged in. |
oauth.xhr = function(options, callback) {
if (!token('oauth_token')) {
if (o.auto) return oauth.authenticate(run);
else return callback('not authenticated', null);
} else return run();
function run() {
var params = timenonce(getAuth(o)),
url = o.url + options.path,
oauth_token_secret = token('oauth_token_secret');
params.oauth_token = token('oauth_token');
params.oauth_signature = ohauth.signature(
o.oauth_secret,
oauth_token_secret,
ohauth.baseString(options.method, url, params));
ohauth.xhr(options.method,
url, params, options.content, options.options, done);
}
function done(err, xhr) {
if (err) return callback(err);
else if (xhr.responseXML) return callback(err, xhr.responseXML);
else return callback(err, xhr.response);
}
};
|
'stamp' an authentication object from |
function timenonce(o) {
o.oauth_timestamp = ohauth.timestamp();
o.oauth_nonce = ohauth.nonce();
return o;
}
|
get/set tokens. These are prefixed with the base URL so that |
function token(x, y) {
if (arguments.length === 1) return store.get(o.url + x);
else if (arguments.length === 2) return store.set(o.url + x, y);
}
|
Get an authentication object. If you just add and remove properties
from a single object, you'll need to use |
function getAuth(o) {
return {
oauth_consumer_key: o.oauth_consumer_key,
oauth_signature_method: "HMAC-SHA1"
};
}
return oauth;
};
|