V3-1839 web satellite auth cookie subdomain differentiation (#2601)
* V3-1839 web satellite auth cookie subdomain differentiation
This commit is contained in:
parent
5b73180f9b
commit
6143be5915
@ -66,7 +66,7 @@
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import HeaderedInput from '@/components/common/HeaderedInput.vue';
|
||||
import Button from '@/components/common/Button.vue';
|
||||
import { removeToken } from '@/utils/tokenManager';
|
||||
import { AuthToken } from '@/utils/authToken';
|
||||
import { APP_STATE_ACTIONS, USER_ACTIONS, NOTIFICATION_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { RequestResponse } from '@/types/response';
|
||||
|
||||
@ -102,7 +102,7 @@
|
||||
}
|
||||
|
||||
this.$store.dispatch(NOTIFICATION_ACTIONS.SUCCESS, 'Account was successfully deleted');
|
||||
removeToken();
|
||||
AuthToken.remove();
|
||||
|
||||
this.isLoading = false;
|
||||
this.$router.push('/login');
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import { removeToken } from '@/utils/tokenManager';
|
||||
import { AuthToken } from '@/utils/authToken';
|
||||
import ROUTES from '@/utils/constants/routerConstants';
|
||||
import {
|
||||
APP_STATE_ACTIONS,
|
||||
@ -52,7 +52,7 @@
|
||||
}
|
||||
|
||||
public onLogoutClick(): void {
|
||||
removeToken();
|
||||
AuthToken.remove();
|
||||
|
||||
this.$router.push(ROUTES.LOGIN.path);
|
||||
this.$store.dispatch(PM_ACTIONS.CLEAR);
|
||||
|
@ -21,7 +21,7 @@ import ProjectDetails from '@/components/project/ProjectDetails.vue';
|
||||
import ProjectBillingHistory from '@/components/project/billing/BillingArea.vue';
|
||||
import ProjectPaymentMethods from '@/components/project/ProjectPaymentMethods.vue';
|
||||
import BucketArea from '@/components/buckets/BucketArea.vue';
|
||||
import { getToken } from '@/utils/tokenManager';
|
||||
import { AuthToken } from '@/utils/authToken';
|
||||
import store from '@/store';
|
||||
|
||||
Vue.use(Router);
|
||||
@ -156,7 +156,7 @@ router.beforeEach((to, from, next) => {
|
||||
}
|
||||
|
||||
if (to.matched.some(route => route.meta.requiresAuth)) {
|
||||
if (!getToken()) {
|
||||
if (!AuthToken.get()) {
|
||||
next(ROUTES.LOGIN);
|
||||
|
||||
return;
|
||||
|
@ -8,12 +8,12 @@ export class User {
|
||||
public email: string;
|
||||
public partnerId: string;
|
||||
|
||||
public constructor(fullName: string, shortName: string, email: string, partnerId: string) {
|
||||
public constructor(fullName: string, shortName: string, email: string, partnerId?: string) {
|
||||
this.id = '';
|
||||
this.fullName = fullName;
|
||||
this.shortName = shortName;
|
||||
this.email = email;
|
||||
this.partnerId = partnerId;
|
||||
this.partnerId = partnerId || '';
|
||||
}
|
||||
|
||||
public getFullName(): string {
|
||||
|
@ -5,7 +5,7 @@ import { HttpLink } from 'apollo-link-http';
|
||||
import ApolloClient from 'apollo-client/ApolloClient';
|
||||
import { InMemoryCache } from 'apollo-cache-inmemory';
|
||||
import { setContext } from 'apollo-link-context';
|
||||
import { getToken } from '@/utils/tokenManager';
|
||||
import { AuthToken } from '@/utils/authToken';
|
||||
|
||||
// Satellite url
|
||||
const satelliteUrl = new HttpLink({
|
||||
@ -15,9 +15,9 @@ const satelliteUrl = new HttpLink({
|
||||
// Adding auth headers
|
||||
const authLink = setContext((_, {headers}) => {
|
||||
// get the authentication token from local storage if it exists
|
||||
const token = getToken();
|
||||
// return the headers to the context so httpLink can read them
|
||||
const token = AuthToken.get();
|
||||
|
||||
// return the headers to the context so httpLink can read them
|
||||
return {
|
||||
headers: {
|
||||
...headers,
|
||||
|
46
web/satellite/src/utils/authToken.ts
Normal file
46
web/satellite/src/utils/authToken.ts
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
// AuthToken exposes methods to manage auth cookie
|
||||
export class AuthToken {
|
||||
private static readonly tokenKeySuffix: string = '_tokenKey';
|
||||
private static tokenKey: string = '_tokenKey';
|
||||
|
||||
public static initialize(): void {
|
||||
AuthToken.tokenKey = (document as any).location.hostname + AuthToken.tokenKeySuffix;
|
||||
}
|
||||
|
||||
public static get(): string {
|
||||
return AuthToken.getCookie(AuthToken.tokenKey);
|
||||
}
|
||||
|
||||
public static set(tokenValue: string): void {
|
||||
document.cookie = AuthToken.tokenKey + '=' + tokenValue + '; path=/';
|
||||
}
|
||||
|
||||
public static remove(): void {
|
||||
document.cookie = AuthToken.tokenKey + '=; path=/';
|
||||
}
|
||||
|
||||
private static getCookie(cname: string): string {
|
||||
let name: string = cname + '=';
|
||||
let decodedCookie: string = decodeURIComponent(document.cookie);
|
||||
let ca: string[] = decodedCookie.split(';');
|
||||
|
||||
for (let i = 0; i < ca.length; i++) {
|
||||
let c = ca[i];
|
||||
|
||||
while (c.charAt(0) === ' ') {
|
||||
c = c.substring(1);
|
||||
}
|
||||
|
||||
if (c.indexOf(name) === 0) {
|
||||
return c.substring(name.length, c.length);
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
AuthToken.initialize();
|
@ -1,36 +0,0 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
const tokenKey: string = 'tokenKey';
|
||||
|
||||
export function getToken(): string {
|
||||
return getCookie(tokenKey);
|
||||
}
|
||||
|
||||
export function setToken(tokenValue: string): void {
|
||||
document.cookie = tokenKey + '=' + tokenValue + '; path=/';
|
||||
}
|
||||
|
||||
export function removeToken(): void {
|
||||
document.cookie = tokenKey + '=; path=/';
|
||||
}
|
||||
|
||||
function getCookie(cname: string): string {
|
||||
let name: string = cname + '=';
|
||||
let decodedCookie: string = decodeURIComponent(document.cookie);
|
||||
let ca: string[] = decodedCookie.split(';');
|
||||
|
||||
for (let i = 0; i < ca.length; i++) {
|
||||
let c = ca[i];
|
||||
|
||||
while (c.charAt(0) === ' ') {
|
||||
c = c.substring(1);
|
||||
}
|
||||
|
||||
if (c.indexOf(name) === 0) {
|
||||
return c.substring(name.length, c.length);
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
@ -24,7 +24,7 @@ import {AppState} from "../utils/constants/appStateEnum";
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import DashboardHeader from '@/components/header/Header.vue';
|
||||
import NavigationArea from '@/components/navigation/NavigationArea.vue';
|
||||
import { removeToken } from '@/utils/tokenManager';
|
||||
import { AuthToken } from '@/utils/authToken';
|
||||
import {
|
||||
API_KEYS_ACTIONS,
|
||||
APP_STATE_ACTIONS,
|
||||
@ -50,7 +50,7 @@ import {AppState} from "../utils/constants/appStateEnum";
|
||||
this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.ERROR);
|
||||
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, response.errorMessage);
|
||||
this.$router.push(ROUTES.LOGIN);
|
||||
removeToken();
|
||||
AuthToken.remove();
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -4,96 +4,96 @@
|
||||
<template src="./login.html"></template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import HeaderlessInput from '@/components/common/HeaderlessInput.vue';
|
||||
import Button from '@/components/common/Button.vue';
|
||||
import { setToken } from '@/utils/tokenManager';
|
||||
import ROUTES from '@/utils/constants/routerConstants';
|
||||
import { APP_STATE_ACTIONS, NOTIFICATION_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { getTokenRequest } from '@/api/users';
|
||||
import { LOADING_CLASSES } from '@/utils/constants/classConstants';
|
||||
import { AppState } from '@/utils/constants/appStateEnum';
|
||||
import { validateEmail, validatePassword } from '@/utils/validation';
|
||||
import EVENTS from '../../utils/constants/analyticsEventNames';
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import HeaderlessInput from '@/components/common/HeaderlessInput.vue';
|
||||
import Button from '@/components/common/Button.vue';
|
||||
import { AuthToken } from '@/utils/authToken';
|
||||
import ROUTES from '@/utils/constants/routerConstants';
|
||||
import { APP_STATE_ACTIONS, NOTIFICATION_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { getTokenRequest } from '@/api/users';
|
||||
import { LOADING_CLASSES } from '@/utils/constants/classConstants';
|
||||
import { AppState } from '@/utils/constants/appStateEnum';
|
||||
import { validateEmail, validatePassword } from '@/utils/validation';
|
||||
import EVENTS from '../../utils/constants/analyticsEventNames';
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
HeaderlessInput,
|
||||
Button
|
||||
}
|
||||
})
|
||||
export default class Login extends Vue {
|
||||
public forgotPasswordRouterPath: string = ROUTES.FORGOT_PASSWORD.path;
|
||||
private email: string = '';
|
||||
private password: string = '';
|
||||
private loadingClassName: string = LOADING_CLASSES.LOADING_OVERLAY;
|
||||
private loadingLogoClassName: string = LOADING_CLASSES.LOADING_LOGO;
|
||||
private emailError: string = '';
|
||||
private passwordError: string = '';
|
||||
@Component({
|
||||
components: {
|
||||
HeaderlessInput,
|
||||
Button
|
||||
}
|
||||
})
|
||||
export default class Login extends Vue {
|
||||
public forgotPasswordRouterPath: string = ROUTES.FORGOT_PASSWORD.path;
|
||||
private email: string = '';
|
||||
private password: string = '';
|
||||
private loadingClassName: string = LOADING_CLASSES.LOADING_OVERLAY;
|
||||
private loadingLogoClassName: string = LOADING_CLASSES.LOADING_LOGO;
|
||||
private emailError: string = '';
|
||||
private passwordError: string = '';
|
||||
|
||||
public onLogoClick(): void {
|
||||
location.reload();
|
||||
}
|
||||
public onLogoClick(): void {
|
||||
location.reload();
|
||||
}
|
||||
|
||||
public setEmail(value: string): void {
|
||||
this.email = value;
|
||||
this.emailError = '';
|
||||
}
|
||||
public setEmail(value: string): void {
|
||||
this.email = value;
|
||||
this.emailError = '';
|
||||
}
|
||||
|
||||
public setPassword(value: string): void {
|
||||
this.password = value;
|
||||
this.passwordError = '';
|
||||
}
|
||||
public setPassword(value: string): void {
|
||||
this.password = value;
|
||||
this.passwordError = '';
|
||||
}
|
||||
|
||||
public onSignUpClick(): void {
|
||||
this.$router.push(ROUTES.REGISTER.path);
|
||||
}
|
||||
public onSignUpClick(): void {
|
||||
this.$router.push(ROUTES.REGISTER.path);
|
||||
}
|
||||
|
||||
public async onLogin(): Promise<void> {
|
||||
let self = this;
|
||||
this.$segment.track(EVENTS.CLICKED_LOGIN);
|
||||
public async onLogin(): Promise<void> {
|
||||
let self = this;
|
||||
this.$segment.track(EVENTS.CLICKED_LOGIN);
|
||||
|
||||
if (!self.validateFields()) {
|
||||
return;
|
||||
}
|
||||
if (!self.validateFields()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let loginResponse = await getTokenRequest(this.email, this.password);
|
||||
if (!loginResponse.isSuccess) {
|
||||
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, loginResponse.errorMessage);
|
||||
let loginResponse = await getTokenRequest(this.email, this.password);
|
||||
if (!loginResponse.isSuccess) {
|
||||
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, loginResponse.errorMessage);
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.activateLoadingOverlay();
|
||||
this.activateLoadingOverlay();
|
||||
|
||||
setTimeout(() => {
|
||||
setToken(loginResponse.data);
|
||||
this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.LOADING);
|
||||
this.$router.push(ROUTES.PROJECT_OVERVIEW.path + '/' + ROUTES.PROJECT_DETAILS.path);
|
||||
}, 2000);
|
||||
}
|
||||
setTimeout(() => {
|
||||
AuthToken.set(loginResponse.data);
|
||||
this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.LOADING);
|
||||
this.$router.push(ROUTES.PROJECT_OVERVIEW.path + '/' + ROUTES.PROJECT_DETAILS.path);
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
private validateFields(): boolean {
|
||||
let isNoErrors = true;
|
||||
private validateFields(): boolean {
|
||||
let isNoErrors = true;
|
||||
|
||||
if (!validateEmail(this.email.trim())) {
|
||||
this.emailError = 'Invalid Email';
|
||||
isNoErrors = false;
|
||||
}
|
||||
if (!validateEmail(this.email.trim())) {
|
||||
this.emailError = 'Invalid Email';
|
||||
isNoErrors = false;
|
||||
}
|
||||
|
||||
if (!validatePassword(this.password)) {
|
||||
this.passwordError = 'Invalid Password';
|
||||
isNoErrors = false;
|
||||
}
|
||||
if (!validatePassword(this.password)) {
|
||||
this.passwordError = 'Invalid Password';
|
||||
isNoErrors = false;
|
||||
}
|
||||
|
||||
return isNoErrors;
|
||||
}
|
||||
return isNoErrors;
|
||||
}
|
||||
|
||||
private activateLoadingOverlay(): void {
|
||||
this.loadingClassName = LOADING_CLASSES.LOADING_OVERLAY_ACTIVE;
|
||||
this.loadingLogoClassName = LOADING_CLASSES.LOADING_LOGO_ACTIVE;
|
||||
}
|
||||
}
|
||||
private activateLoadingOverlay(): void {
|
||||
this.loadingClassName = LOADING_CLASSES.LOADING_OVERLAY_ACTIVE;
|
||||
this.loadingLogoClassName = LOADING_CLASSES.LOADING_LOGO_ACTIVE;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style src="./login.scss" scoped lang="scss"></style>
|
||||
|
Loading…
Reference in New Issue
Block a user