diff --git a/app/org/thp/cortex/services/OAuth2Srv.scala b/app/org/thp/cortex/services/OAuth2Srv.scala index 33b3d1780..a8f7be1c1 100644 --- a/app/org/thp/cortex/services/OAuth2Srv.scala +++ b/app/org/thp/cortex/services/OAuth2Srv.scala @@ -91,7 +91,9 @@ class OAuth2Srv( private def getAuthTokenAndAuthenticate(clientId: String, code: String)(implicit request: RequestHeader): Future[AuthContext] = { logger.debug("Getting user token with the code from the response!") withOAuth2Config { cfg ⇒ + val acceptHeader = "Accept" → cfg.responseType ws.url(cfg.tokenUrl) + .addHttpHeaders(acceptHeader) .post(Map( "code" → code, "grant_type" → cfg.grantType, diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 10c90f101..364d0ce38 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -18,7 +18,7 @@ object Dependencies { val reflections = "org.reflections" % "reflections" % "0.9.11" val zip4j = "net.lingala.zip4j" % "zip4j" % "1.3.2" - val elastic4play = "org.thehive-project" %% "elastic4play" % "1.9.1-SNAPSHOT" + val elastic4play = "org.thehive-project" %% "elastic4play" % "1.10.0" val dockerClient = "com.spotify" % "docker-client" % "8.14.4" } diff --git a/www/package.json b/www/package.json index 22c06c72e..bafbe736a 100755 --- a/www/package.json +++ b/www/package.json @@ -53,6 +53,7 @@ "html-loader": "^0.4.4", "html-webpack-plugin": "^2.22.0", "jquery": "^3.2.1", + "js-url": "^2.3.0", "lodash": "^4.17.4", "manifest-revision-webpack-plugin": "^0.3.0", "moment": "^2.20.1", diff --git a/www/src/app/core/services/common/AuthService.js b/www/src/app/core/services/common/AuthService.js index 659009f60..7eebe9508 100644 --- a/www/src/app/core/services/common/AuthService.js +++ b/www/src/app/core/services/common/AuthService.js @@ -27,9 +27,21 @@ export default class AuthService { return defer.promise; } + ssoLogin(code) { + let defer = this.$q.defer(); + + this.$http + .post(angular.isDefined(code) ? './api/ssoLogin?code=' + code : './api/ssoLogin') + .then(response => defer.resolve(response)) + .catch(err => defer.reject(err)); + + return defer.promise; + } + logout() { return this.$http.get('./api/logout').then( - /*data*/ () => { + /*data*/ + () => { this.currentUser = null; } ); @@ -69,4 +81,4 @@ export default class AuthService { return !_.isEmpty(_.intersection(this.currentUser.roles, roles)); } -} +} \ No newline at end of file diff --git a/www/src/app/core/services/constants.js b/www/src/app/core/services/constants.js index 7758cb76f..1b0f050b7 100755 --- a/www/src/app/core/services/constants.js +++ b/www/src/app/core/services/constants.js @@ -1,7 +1,8 @@ 'use strict'; -export default function(app) { +export default function (app) { app + .constant('UrlParser', window.url) .constant('ROUTE_ERRORS', { auth: 'Authorization has been denied.' }) @@ -11,8 +12,7 @@ export default function(app) { ANALYZE: 'analyze', READ: 'read' }) - .value('Tlps', [ - { + .value('Tlps', [{ key: 'WHITE', value: 0 }, @@ -29,4 +29,4 @@ export default function(app) { value: 3 } ]); -} +} \ No newline at end of file diff --git a/www/src/app/index.vendor.js b/www/src/app/index.vendor.js index 63ada7239..3d05a6d6c 100755 --- a/www/src/app/index.vendor.js +++ b/www/src/app/index.vendor.js @@ -48,3 +48,5 @@ import 'angular-input-masks'; import 'font-awesome/css/font-awesome.css'; import 'angular-ui-notification/dist/angular-ui-notification.css'; import 'css-spaces/dist/spaces.css'; + +import 'js-url'; \ No newline at end of file diff --git a/www/src/app/pages/login/login.controller.js b/www/src/app/pages/login/login.controller.js index 6d6dcc3f6..dc51b9273 100644 --- a/www/src/app/pages/login/login.controller.js +++ b/www/src/app/pages/login/login.controller.js @@ -3,17 +3,23 @@ export default class LoginController { $log, $state, $uibModalStack, + $location, + $stateParams, AuthService, NotificationService, - Roles + Roles, + UrlParser ) { 'ngInject'; this.$log = $log; this.$state = $state; this.$uibModalStack = $uibModalStack; + this.$location = $location; + this.$stateParams = $stateParams; this.AuthService = AuthService; this.NotificationService = NotificationService; this.Roles = Roles; + this.UrlParser = UrlParser; this.params = { bar: 'foo' }; @@ -23,8 +29,29 @@ export default class LoginController { this.params.username = angular.lowercase(this.params.username); this.AuthService.login(this.params.username, this.params.password) - .then(() => { - this.$state.go('index'); + .then(() => this.$state.go('index')) + .catch(err => { + if (err.status === 520) { + this.NotificationService.handleError( + 'LoginController', + err.data, + err.status + ); + } else { + this.NotificationService.log(err.data.message, 'error'); + } + }); + } + + ssoLogin(code) { + this.AuthService.ssoLogin(code) + .then(response => { + let redirectLocation = response.headers().location; + if (angular.isDefined(redirectLocation)) { + window.location = redirectLocation; + } else { + this.$state.go('index'); + } }) .catch(err => { if (err.status === 520) { @@ -35,11 +62,21 @@ export default class LoginController { ); } else { this.NotificationService.log(err.data.message, 'error'); + this.$location.url(this.$location.path()); } }); } + ssoEnabled() { + return this.config.config.authType.indexOf('oauth2') !== -1; + } + $onInit() { this.$uibModalStack.dismissAll(); + + let code = (this.UrlParser('?') || {}).code; + if (angular.isDefined(code) || this.$stateParams.autoLogin) { + this.ssoLogin(code); + } } -} +} \ No newline at end of file diff --git a/www/src/app/pages/login/login.module.js b/www/src/app/pages/login/login.module.js index 212673120..5bb20baab 100644 --- a/www/src/app/pages/login/login.module.js +++ b/www/src/app/pages/login/login.module.js @@ -3,6 +3,8 @@ import LoginController from './login.controller'; import tpl from './login.page.html'; +import './login.page.scss'; + const loginPageModule = angular .module('login-module', ['ui.router']) .config($stateProvider => { @@ -10,12 +12,22 @@ const loginPageModule = angular $stateProvider.state('login', { url: '/login', - component: 'loginPage' + component: 'loginPage', + resolve: { + config: ($q, VersionService) => VersionService.get() + .then(response => $q.resolve(response.data)) + }, + params: { + autoLogin: false + } }); }) .component('loginPage', { controller: LoginController, - templateUrl: tpl + templateUrl: tpl, + bindings: { + config: '<' + } }); -export default loginPageModule; +export default loginPageModule; \ No newline at end of file diff --git a/www/src/app/pages/login/login.page.html b/www/src/app/pages/login/login.page.html index 6d8424406..90a3af416 100644 --- a/www/src/app/pages/login/login.page.html +++ b/www/src/app/pages/login/login.page.html @@ -21,4 +21,11 @@ +
+
+
+ +
+
+
\ No newline at end of file diff --git a/www/src/app/pages/login/login.page.scss b/www/src/app/pages/login/login.page.scss new file mode 100644 index 000000000..2f9f4df77 --- /dev/null +++ b/www/src/app/pages/login/login.page.scss @@ -0,0 +1,4 @@ +.sso-login-box { + margin-top: 20px; + text-align: center; +} \ No newline at end of file diff --git a/www/src/app/pages/main/main.controller.js b/www/src/app/pages/main/main.controller.js index e38c5bc69..4a368ac0a 100755 --- a/www/src/app/pages/main/main.controller.js +++ b/www/src/app/pages/main/main.controller.js @@ -12,8 +12,10 @@ export default class MainController { this.$state.go('maintenance'); return; } else if (!this.currentUser || !this.currentUser.id) { - this.$state.go('login'); + this.$state.go('login', { + autoLogin: (this.config || {}).ssoAutoLogin + }); return; } } -} +} \ No newline at end of file