diff --git a/monkey_island/cc/ui/package.json b/monkey_island/cc/ui/package.json index 5ee2e5389..e8fb04eaf 100644 --- a/monkey_island/cc/ui/package.json +++ b/monkey_island/cc/ui/package.json @@ -65,6 +65,7 @@ "core-js": "^2.5.1", "fetch": "^1.1.0", "js-file-download": "^0.4.1", + "jwt-decode": "^2.2.0", "normalize.css": "^4.0.0", "prop-types": "^15.5.10", "rc-progress": "^2.2.5", diff --git a/monkey_island/cc/ui/src/components/AuthComponent.js b/monkey_island/cc/ui/src/components/AuthComponent.js new file mode 100644 index 000000000..428c3272a --- /dev/null +++ b/monkey_island/cc/ui/src/components/AuthComponent.js @@ -0,0 +1,12 @@ +import React from 'react'; +import AuthService from '../services/AuthService'; + +class AuthComponent extends React.Component { + constructor(props) { + super(props); + this.auth = new AuthService(); + this.authFetch = this.auth.authFetch; + } +} + +export default AuthComponent; diff --git a/monkey_island/cc/ui/src/services/AuthService.js b/monkey_island/cc/ui/src/services/AuthService.js new file mode 100644 index 000000000..36e352ed4 --- /dev/null +++ b/monkey_island/cc/ui/src/services/AuthService.js @@ -0,0 +1,84 @@ +import decode from 'jwt-decode'; + +export default class AuthService { + AUTH_ENABLED = true; + + login = (username, password) => { + if (this.AUTH_ENABLED) { + return this._login(username, password); + } else { + return {}; + } + }; + + authFetch = (url, options) => { + if (this.AUTH_ENABLED) { + return this._authFetch(url, options); + } else { + return fetch(url, options); + } + }; + + _login = (username, password) => { + return this._authFetch('/api/auth', { + method: 'POST', + body: JSON.stringify({ + username, + password + }) + }).then(response => response.json()) + .then(res => { + this._setToken(res['access_token']); + }) + }; + + _authFetch = (url, options) => { + const headers = { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }; + + if (this.loggedIn()) { + headers['Authorization'] = 'JWT ' + this._getToken(); + } + + return fetch(url, { + headers, + ...options + }); + + }; + + loggedIn() { + if (!this.AUTH_ENABLED) { + return true; + } + const token = this._getToken(); + return (token && !this._isTokenExpired(token)); + } + + logout() { + if (this.AUTH_ENABLED) { + localStorage.removeItem('jwt'); + } + } + + _isTokenExpired(token) { + try { + return decode(token)['exp'] < Date.now() / 1000; + } + catch (err) { + return false; + } + } + + _setToken(idToken) { + localStorage.setItem('jwt', idToken); + } + + _getToken() { + return localStorage.getItem('jwt') + } + + +}