+
+ First, you'll need to get a GitHub Client ID. Follow these steps:
+
+
+ -
+ Visit your enterprise GitHub site and go to
Settings -> Developer settings -> OAuth Apps -> New OAuth App
+
+ -
+ Set Homepage URL to: {{siteUrl}}
+
+ -
+ Set Authorization callback URL to: {{siteUrl}}_oauth/ghe
+
+
+
diff --git a/packages/ghe/ghe_configure.js b/packages/ghe/ghe_configure.js
new file mode 100755
index 00000000..5246c442
--- /dev/null
+++ b/packages/ghe/ghe_configure.js
@@ -0,0 +1,13 @@
+/* eslint-disable no-undef */
+
+Template.configureLoginServiceDialogForGhe.helpers({
+ siteUrl: function() {
+ return Meteor.absoluteUrl();
+ }
+});
+
+Template.configureLoginServiceDialogForGhe.fields = () => [
+ { property: 'gheURL', label: 'GitHub Enterprise URL' },
+ { property: 'clientId', label: 'Client ID' },
+ { property: 'secret', label: 'Client Secret' }
+];
diff --git a/packages/ghe/ghe_login_button.css b/packages/ghe/ghe_login_button.css
new file mode 100755
index 00000000..1506bfc3
--- /dev/null
+++ b/packages/ghe/ghe_login_button.css
@@ -0,0 +1,3 @@
+#login-buttons-image-ghe {
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wJGBYxHYxl31wAAAHpSURBVDjLpZI/aFNRFMZ/973bJqGRPopV4qNq/+SpTYnWRhCKilShg9BGcHOM+GfQoZuLk4iLgw4qZNBaHLuIdBNHl7Ta1qdNFI3SihnaNG1MpH3vuiQYQnwZvHCG893zffc751z4z6PX5T5gA1DAKnAaOAQEgAfAVeCpl+CeCrlRuEC6maO4h0A1wl4tPAHMqNUthvrDdHYY7A3t4rDVjeO6rBU2FaABM1WCrBNoi48Mi+nH9yj+KtPibAKwJXfQ5vcRG7soUnYmWEuQgAEIYBv4cGpoILI0Z4tyYYPegS6UguyijZQ6J45GSNmZHzUcJYD2ii2Ajv7efZ8WZ6ZwXFj79hXpayW4O0SL1Nl/8jzZlZ9dQLFS70pgvZKIyGD0yvu5eRmMnrk1PjI81ir1qBACTdPevXj95mVuNX8XKDQc/+T334bZZ104cvzYw2s3J3qAL5WXSsDbf61NNMBu+wOBs+VSyQ84Nfhg028ZGx3/qyy0lC7lgi7lghBitoon03lvB8l0/k7Wnk+8mny0cyXzEcfZxgwfZPTyRMHsOzAFXE9YhtNQIJnOx4FpJXT1eSkn2g0frqMoFrfoCXcqlCOAGwnLuO/l4JymcWl5uRxzXUKghBAiZ5r+WaV4lrCM555zqO+x2d0ftGmpiA/0k70AAAAASUVORK5CYII=);
+}
diff --git a/packages/ghe/ghe_server.js b/packages/ghe/ghe_server.js
new file mode 100755
index 00000000..a3d87215
--- /dev/null
+++ b/packages/ghe/ghe_server.js
@@ -0,0 +1,118 @@
+/* eslint-disable no-undef */
+
+Ghe = {};
+
+OAuth.registerService('ghe', 2, null, function(query) {
+
+ const accessToken = getAccessToken(query);
+ const identity = getIdentity(accessToken);
+ const emails = getEmails(accessToken);
+ const primaryEmail = emails.find(email => email.primary);
+
+ return {
+ serviceData: {
+ id: identity.id,
+ accessToken: OAuth.sealSecret(accessToken),
+ email: identity.email || (primaryEmail && primaryEmail.email) || '',
+ username: identity.login,
+ emails: emails
+ },
+ options: { profile: { name: identity.name } }
+ };
+});
+
+const apiPath = 'api/v3';
+
+// http://developer.github.com/v3/#user-agent-required
+let userAgent = 'Meteor';
+if (Meteor.release) {
+ userAgent += '/' + Meteor.release;
+}
+
+const getAccessToken = function(query) {
+ const config = ServiceConfiguration.configurations.findOne({ service: 'ghe' });
+ if (!config) {
+ throw new ServiceConfiguration.ConfigError();
+ }
+
+ let response;
+ try {
+ const gheUrl = sanitizeUrl(config.gheURL);
+ response = HTTP.post(`${gheUrl}/login/oauth/access_token`, {
+ headers: {
+ Accept: 'application/json',
+ 'User-Agent': userAgent
+ },
+ params: {
+ code: query.code,
+ client_id: config.clientId,
+ client_secret: OAuth.openSecret(config.secret),
+ redirect_uri: OAuth._redirectUri('ghe', config),
+ state: query.state
+ }
+ });
+ } catch (err) {
+ throw Object.assign(
+ new Error(`Failed to complete OAuth handshake with Github Enterprise. ${err.message}`),
+ { response: err.response },
+ );
+ }
+
+ if (response.data.error) { // if the http response was a json object with an error attribute
+ throw new Error('Failed to complete OAuth handshake with GitHub Enterprise. ' + response.data.error);
+ } else {
+ return response.data.access_token;
+ }
+};
+
+const getIdentity = function(accessToken) {
+ const config = ServiceConfiguration.configurations.findOne({ service: 'ghe' });
+ if (!config) {
+ throw new ServiceConfiguration.ConfigError();
+ }
+
+ try {
+ const gheUrl = sanitizeUrl(config.gheURL);
+ return HTTP.get(`${gheUrl}/${apiPath}/user`, {
+ headers: {'User-Agent': userAgent, 'Authorization': `token ${accessToken}`},
+ }).data;
+ } catch (err) {
+ throw Object.assign(
+ new Error(`Failed to fetch identity from Github. ${err.message}`),
+ { response: err.response },
+ );
+ }
+};
+
+const getEmails = function(accessToken) {
+ const config = ServiceConfiguration.configurations.findOne({ service: 'ghe' });
+ if (!config) {
+ throw new ServiceConfiguration.ConfigError();
+ }
+
+ try {
+ const gheUrl = sanitizeUrl(config.gheURL);
+ return HTTP.get( `${gheUrl}/${apiPath}/user/emails`, {
+ headers: {'User-Agent': userAgent, 'Authorization': `token ${accessToken}`},
+ }).data;
+ } catch (err) {
+ return [];
+ }
+};
+
+const sanitizeUrl = (url) => {
+
+ const httpCheck = /^((http|https):\/\/)/;
+ if(!httpCheck.test(url)) {
+ url = `https://${url}`;
+ }
+
+ const trailingSlash = /\/*$/gi;
+ const ghe = url.replace(trailingSlash, '');
+
+ return ghe;
+};
+
+Ghe.retrieveCredential = function(credentialToken, credentialSecret) {
+ return OAuth.retrieveCredential(credentialToken, credentialSecret);
+};
diff --git a/packages/ghe/package.js b/packages/ghe/package.js
new file mode 100755
index 00000000..c011dbd8
--- /dev/null
+++ b/packages/ghe/package.js
@@ -0,0 +1,30 @@
+/* eslint-disable no-undef */
+
+Package.describe({
+ summary: 'Github Enterprise OAuth flow',
+ version: '3.0.0',
+ name: 'ibmcloud:accounts-ghe',
+ documentation: null
+});
+
+Package.onUse(function(api) {
+ api.use('accounts-base', ['client', 'server']);
+ api.use('ecmascript');
+ api.imply('accounts-base', ['client', 'server']);
+ api.use('accounts-oauth', ['client', 'server']);
+ api.use('oauth2', ['client', 'server']);
+ api.use('oauth', ['client', 'server']);
+ api.use('http', ['client', 'server']);
+ api.use('underscore', 'client');
+ api.use('templating', 'client');
+ api.use('random', 'client');
+ api.use('service-configuration', ['client', 'server']);
+ api.addFiles('ghe_login_button.css', 'client');
+ api.addFiles('ghe.js');
+ api.export('Ghe');
+ api.addFiles(
+ ['ghe_configure.html', 'ghe_configure.js'],
+ 'client');
+ api.addFiles('ghe_server.js', 'server');
+ api.addFiles('ghe_client.js', 'client');
+});