Skip to content

Instantly share code, notes, and snippets.

Created April 18, 2015 23:33
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/357852f8770155341a6a to your computer and use it in GitHub Desktop.
Save anonymous/357852f8770155341a6a to your computer and use it in GitHub Desktop.
Meteor OAuth with Microsoft (eg Hotmail, Live.com etc)
// Write your tests here!
// Here is an example.
Tinytest.add('example', function (test) {
test.equal(true, true);
});
/**
* Created by adamginsburg on 3/04/2015.
*/
MicrosoftOauth = {};
MicrosoftOauth.requestCredential = function (options, credentialRequestCompleteCallback) {
// support both (options, callback) and (callback).
if (!credentialRequestCompleteCallback && typeof options === 'function') {
credentialRequestCompleteCallback = options;
options = {};
}
var config = ServiceConfiguration.configurations.findOne({service: 'microsoft'});
if (!config) {
credentialRequestCompleteCallback && credentialRequestCompleteCallback(
new ServiceConfiguration.ConfigError());
return;
}
var credentialToken = Random.secret();
var mobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i.test(navigator.userAgent);
var display = mobile ? 'touch' : 'popup';
var scope = "email";
if (options && options.requestPermissions)
scope = options.requestPermissions.join(',');
console.log("MicrosoftOauth 2 config:", config);
var loginStyle = OAuth._loginStyle('microsoft', config, options);
var loginUrl =
'https://login.live.com/oauth20_authorize.srf?client_id=' + config.clientId +
'&redirect_uri=' + Meteor.absoluteUrl("_oauth/microsoft") +
'&response_type=' + "code" +
'&display=' + display + '&scope=' + config.scope +
'&state=' + OAuth._stateParam(loginStyle, credentialToken);
OAuth.launchLogin({
loginService: "microsoft",
loginStyle: loginStyle,
loginUrl: loginUrl,
credentialRequestCompleteCallback: credentialRequestCompleteCallback,
credentialToken: credentialToken
});
};
Meteor.loginWithMicrosoft = function (options, callback) {
// support a callback without options
if (!callback && typeof options === "function") {
callback = options;
options = null;
}
var credentialRequestCompleteCallback = Accounts.oauth.credentialRequestCompleteHandler(callback);
MicrosoftOauth.requestCredential(options, credentialRequestCompleteCallback);
};
/**
* Created by adamginsburg on 3/04/2015.
*/
MicrosoftOauth = {};
MicrosoftOauth.whitelistedFields = ['user_id', 'name', 'first_name', 'last_name', 'email'];
OAuth.registerService('microsoft', 2, null, function (oauthBinding) {
//console.log("OAuth.registerService 2:", oauthBinding)
var response = getTokenResponse(oauthBinding);
var accessToken = response.accessToken;
var identity = getIdentity(accessToken);
console.log("identity", identity);
var serviceData = {
id: identity.user_id,
//screenName: identity.screen_name,
accessToken: OAuth.sealSecret(oauthBinding.accessToken),
accessTokenSecret: OAuth.sealSecret(oauthBinding.accessTokenSecret)
};
// include helpful fields from twitter
var fields = _.pick(identity, MicrosoftOauth.whitelistedFields);
_.extend(serviceData, fields);
return {
serviceData: serviceData,
options: {
profile: {
name: identity.name,
}
}
};
});
MicrosoftOauth.retrieveCredential = function (credentialToken, credentialSecret) {
return OAuth.retrieveCredential(credentialToken, credentialSecret);
};
// returns an object containing:
// - accessToken
// - expiresIn: lifetime of token in seconds
var getTokenResponse = function (query) {
//console.log("query", query);
var config = ServiceConfiguration.configurations.findOne({service: 'microsoft'});
if (!config) {
throw new ServiceConfiguration.ConfigError("Service not configured");
}
var responseContent;
try {
// Request an access token
responseContent = HTTP.post(
"https://login.live.com/oauth20_token.srf", {
params: {
client_id: config.clientId,
client_secret: config.secret,
code: query.code,
grant_type: 'authorization_code',
redirect_uri: Meteor.absoluteUrl("_oauth/microsoft")
}
}).content;
console.log("responseContent:", responseContent);
} catch (err) {
throw _.extend(new Error("Failed to complete OAuth handshake with microsoft. " + err.message),
{response: err.response});
}
var parsedResponse = JSON.parse(responseContent);
if (!parsedResponse.access_token) {
throw new Error("Failed to complete OAuth handshake with Microsoft " +
"-- can't find access token in HTTP response. " + parsedResponse);
}
return {
accessToken: parsedResponse.access_token,
microsoftExpires: (+new Date) + (1000 * parsedResponse.expires_in)
}
};
var getIdentity = function (accessToken) {
try {
var responseData = HTTP.get(
"https://apis.live.net/v5.0/me", {
params: {
access_token: accessToken,
}
}).data;
console.log("***************** responseContent 2:", responseData);
var microsoftAccessToken = accessToken;
var microsoft_id = responseData.id;
} catch (err) {
throw _.extend(new Error("Failed to get user details. " + err.message),
{response: err.response});
}
return {
accessToken: microsoftAccessToken,
user_id: microsoft_id,
name: responseData.name,
email: responseData.emails.preferred
};
}
Package.describe({
name: 'adamgins:microsoft-oauth',
version: '0.0.1',
// Brief, one-line summary of the package.
summary: 'Login with hotmail etc',
// URL to the Git repository containing the source code for this package.
git: '',
// By default, Meteor will default to using README.md for documentation.
// To avoid submitting documentation, set this field to null.
documentation: 'README.md'
});
Package.onUse(function(api) {
api.use('http', ['client', 'server']);
api.use('templating', 'client');
api.use('oauth1', ['client', 'server']);
api.use('oauth', ['client', 'server']);
api.use('random', 'client');
api.use('underscore', 'server');
api.use('service-configuration', ['client', 'server']);
api.export('MicrosoftOauth');
api.addFiles('microsoft_client.js','client');
api.addFiles('microsoft_server.js','server');
});
Package.onTest(function(api) {
api.use('tinytest');
api.use('adamgins:microsoft-oauth');
api.addFiles('microsoft-oauth-tests.js');
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment