mirror of https://github.com/rancher/ui.git
182 lines
5.4 KiB
JavaScript
182 lines
5.4 KiB
JavaScript
import Route from '@ember/routing/route';
|
|
import RSVP from 'rsvp';
|
|
import { get } from '@ember/object';
|
|
import { inject as service } from '@ember/service';
|
|
import C from 'shared/utils/constants';
|
|
import { addQueryParams, parseUrl } from 'shared/utils/util';
|
|
import { reject } from 'rsvp';
|
|
import VerifyAuth from 'ui/mixins/verify-auth';
|
|
|
|
const samlProviders = ['ping', 'adfs', 'keycloak', 'okta', 'shibboleth'];
|
|
const allowedForwards = ['localhost'];
|
|
|
|
export default Route.extend(VerifyAuth, {
|
|
oauth: service(),
|
|
intl: service(),
|
|
azureAD: service(),
|
|
language: service('user-language'),
|
|
|
|
beforeModel() {
|
|
if (!this.intl.locale) {
|
|
return get(this, 'language').initUnauthed();
|
|
}
|
|
},
|
|
|
|
model(params/* , transition */) {
|
|
const oauth = get(this, 'oauth');
|
|
const azure = get(this, 'azureAD');
|
|
|
|
const forward = get(params, 'forward');
|
|
|
|
// Allow another redirect if the hostname is in the whitelist above.
|
|
// This allows things like sharing github auth between rancher at localhost:8000
|
|
// and rio dev at localhost:8004
|
|
if ( forward ) {
|
|
const parsed = parseUrl(forward);
|
|
|
|
if ( allowedForwards.includes(parsed.hostname.toLowerCase()) ) {
|
|
if ( get(params, 'login') ) {
|
|
window.location.href = addQueryParams(forward, {
|
|
forwarded: 'true',
|
|
code
|
|
});
|
|
} else {
|
|
oauth.login(forward);
|
|
}
|
|
} else {
|
|
return reject(new Error('Invalid forward url'));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (get(params, 'errorCode')) {
|
|
let errorMessageKey = get(params, 'errorMsg') || null;
|
|
let errorMessageTranslation = this.intl.t('loginPage.error.unknown');
|
|
let locale = this.intl.locale || ['en-us'];
|
|
|
|
if (errorMessageKey && this.intl.exists(`loginPage.error.${ errorMessageKey }`, locale)) {
|
|
errorMessageTranslation = this.intl.t(`loginPage.error.${ errorMessageKey }`);
|
|
}
|
|
|
|
reply(errorMessageTranslation, get(params, 'errorCode'));
|
|
}
|
|
|
|
|
|
|
|
const code = get(params, 'code');
|
|
const state = get(params, 'state')
|
|
|
|
/*
|
|
presence of window.opener indicates this is inital setup popup, not login
|
|
handle auth enable
|
|
*/
|
|
if (window.opener){
|
|
let openersOauth = window.opener.ls('oauth');
|
|
let openerStore = window.opener.ls('globalStore');
|
|
let openersAzure = window.opener.ls('azure-ad')
|
|
|
|
if (!state){
|
|
let provider = get(params, 'config') || get(params, 'authProvider')
|
|
let type = `${ provider }Config`;
|
|
let config = openerStore.getById(type, provider);
|
|
|
|
// do nothing & close popup for saml
|
|
if ( samlProviders.includes(provider) ) {
|
|
if ( window.opener.window.onAuthTest ) {
|
|
reply(null, config);
|
|
} else {
|
|
reply({ err: 'failure' });
|
|
}
|
|
} else if (provider === 'azuread'){
|
|
return azure.testConfig(config).then((resp) => {
|
|
azure.test(resp, openersAzure.get('state'));
|
|
}).catch((err) => {
|
|
reply({ err });
|
|
});
|
|
} else {
|
|
// redirect to 3rd party login for oauth
|
|
return oauth.testConfig(config).then((resp) => {
|
|
oauth.authorize(resp, openersOauth.get('state'));
|
|
}).catch((err) => {
|
|
reply({ err });
|
|
});
|
|
}
|
|
// if state is defined, this route was hit via redirect from 3rd party auth;
|
|
// validate nonce and close window
|
|
} else {
|
|
let stateMsg = 'Authorization state did not match, please try again.';
|
|
let parsedState
|
|
|
|
try {
|
|
parsedState = JSON.parse(oauth.decodeState(state))
|
|
} catch {
|
|
reply({ err: 'nonce' })
|
|
}
|
|
// handle github/google/azuread
|
|
if ( get(params, 'code') ) {
|
|
let openers = openersOauth
|
|
|
|
if ( openers.stateMatches(get(parsedState, 'nonce')) ) {
|
|
reply(params.error_description, params.code);
|
|
} else {
|
|
reply(stateMsg);
|
|
}
|
|
|
|
// handle bitbucket
|
|
} else if ( get(params, 'oauth_token') && get(params, 'oauth_verifier') ) {
|
|
reply(null, {
|
|
oauthToken: get(params, 'oauth_token'),
|
|
oauthVerifier: get(params, 'oauth_verifier'),
|
|
});
|
|
}
|
|
}
|
|
// handle login verification
|
|
} else {
|
|
let parsedState
|
|
|
|
try {
|
|
parsedState = JSON.parse(oauth.decodeState(state))
|
|
} catch {
|
|
reply({ err: 'nonce' })
|
|
}
|
|
if (oauth.stateMatches(parsedState.nonce)){
|
|
const providerType = parsedState.provider
|
|
|
|
const currentProvider = get(this, 'access.providers').findBy('id', providerType);
|
|
|
|
return currentProvider.doAction('login', {
|
|
code,
|
|
responseType: 'cookie',
|
|
description: C.SESSION.DESCRIPTION,
|
|
ttl: C.SESSION.TTL,
|
|
}).then(() => {
|
|
return get(this, 'access').detect()
|
|
.then(() => this.transitionTo('authenticated'));
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function reply(err, code) {
|
|
try {
|
|
let cb = window.opener.window.onAuthTest
|
|
|
|
if (window.opener.window.onAzureTest){
|
|
cb = window.opener.window.onAzureTest
|
|
}
|
|
cb(err, code);
|
|
setTimeout(() => {
|
|
window.close();
|
|
}, 250);
|
|
|
|
return new RSVP.promise();
|
|
} catch (e) {
|
|
window.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
});
|