diff --git a/src/Squidex/Configurations/Identity/LazyClientStore.cs b/src/Squidex/Configurations/Identity/LazyClientStore.cs index 6eb729a3e..92aad733a 100644 --- a/src/Squidex/Configurations/Identity/LazyClientStore.cs +++ b/src/Squidex/Configurations/Identity/LazyClientStore.cs @@ -47,6 +47,10 @@ namespace Squidex.Configurations.Identity ClientName = id, RedirectUris = new List { + options.BuildUrl("#/login;"), + options.BuildUrl("#/logout;"), + options.BuildUrl("login;"), + options.BuildUrl("logout;"), options.BuildUrl("identity-server/client-callback-silent/"), options.BuildUrl("identity-server/client-callback-popup/") }, diff --git a/src/Squidex/Configurations/Identity/MyIdentityOptions.cs b/src/Squidex/Configurations/Identity/MyIdentityOptions.cs index de266618e..388545327 100644 --- a/src/Squidex/Configurations/Identity/MyIdentityOptions.cs +++ b/src/Squidex/Configurations/Identity/MyIdentityOptions.cs @@ -5,6 +5,9 @@ // Copyright (c) Squidex Group // All rights reserved. // ========================================================================== + +using System; + namespace Squidex.Configurations.Identity { public sealed class MyIdentityOptions @@ -23,7 +26,14 @@ namespace Squidex.Configurations.Identity public string BuildUrl(string path) { - return $"{BaseUrl.TrimEnd('/')}/{path.Trim('/')}/"; + var url = $"{BaseUrl.TrimEnd('/')}/{path.Trim('/')}"; + + if (url.IndexOf("?", StringComparison.OrdinalIgnoreCase) < 0 && + url.IndexOf(";", StringComparison.OrdinalIgnoreCase) < 0) { + url = url + "/"; + } + + return url; } } } diff --git a/src/Squidex/Startup.cs b/src/Squidex/Startup.cs index 822f251ac..3c6eac834 100644 --- a/src/Squidex/Startup.cs +++ b/src/Squidex/Startup.cs @@ -149,11 +149,20 @@ namespace Squidex { app.UseDeveloperExceptionPage(); app.UseWebpackProxy(); - app.UseDefaultFiles(); + + app.Use((context, next) => { + context.Request.Path = new PathString("/index.html"); + + return next(); + }); } else { - app.UseDefaultFiles(new DefaultFilesOptions { DefaultFileNames = new List { "build/index.html" } }); + app.Use((context, next) => { + context.Request.Path = new PathString("/build/index.html"); + + return next(); + }); } app.UseStaticFiles(); diff --git a/src/Squidex/app/app.routes.ts b/src/Squidex/app/app.routes.ts index b74d4f669..c8595ebd7 100644 --- a/src/Squidex/app/app.routes.ts +++ b/src/Squidex/app/app.routes.ts @@ -10,7 +10,8 @@ import * as Ng2Router from '@angular/router'; import { AppsPageComponent, - LoginPageComponent + LoginPageComponent, + LogoutPageComponent } from './components'; import { @@ -31,7 +32,11 @@ export const routes: Ng2Router.Routes = [ { path: 'login', component: LoginPageComponent + }, + { + path: 'logout', + component: LogoutPageComponent } ]; -export const routing: Ng2.ModuleWithProviders = Ng2Router.RouterModule.forRoot(routes, { useHash: true }); \ No newline at end of file +export const routing: Ng2.ModuleWithProviders = Ng2Router.RouterModule.forRoot(routes, { useHash: false }); \ No newline at end of file diff --git a/src/Squidex/app/components/login/login.module.ts b/src/Squidex/app/components/auth/auth.module.ts similarity index 71% rename from src/Squidex/app/components/login/login.module.ts rename to src/Squidex/app/components/auth/auth.module.ts index add4240f6..7571b5af9 100644 --- a/src/Squidex/app/components/login/login.module.ts +++ b/src/Squidex/app/components/auth/auth.module.ts @@ -10,7 +10,8 @@ import * as Ng2 from '@angular/core'; import { SqxFrameworkModule } from './../../framework'; import { - LoginPageComponent + LoginPageComponent, + LogoutPageComponent } from './declarations'; @Ng2.NgModule({ @@ -18,7 +19,8 @@ import { SqxFrameworkModule ], declarations: [ - LoginPageComponent + LoginPageComponent, + LogoutPageComponent ] }) export class SqxLoginModule { } \ No newline at end of file diff --git a/src/Squidex/app/components/login/declarations.ts b/src/Squidex/app/components/auth/declarations.ts similarity index 56% rename from src/Squidex/app/components/login/declarations.ts rename to src/Squidex/app/components/auth/declarations.ts index 830720b45..59e51248c 100644 --- a/src/Squidex/app/components/login/declarations.ts +++ b/src/Squidex/app/components/auth/declarations.ts @@ -5,4 +5,5 @@ * Copyright (c) Sebastian Stehle. All rights reserved */ -export * from './login-page.component'; \ No newline at end of file +export * from './login-page.component'; +export * from './logout-page.component'; \ No newline at end of file diff --git a/src/Squidex/app/components/login/index.ts b/src/Squidex/app/components/auth/index.ts similarity index 81% rename from src/Squidex/app/components/login/index.ts rename to src/Squidex/app/components/auth/index.ts index 4ec27fcf1..25d07ecaf 100644 --- a/src/Squidex/app/components/login/index.ts +++ b/src/Squidex/app/components/auth/index.ts @@ -7,4 +7,4 @@ export * from './declarations'; -export * from './login.module'; \ No newline at end of file +export * from './auth.module'; \ No newline at end of file diff --git a/src/Squidex/app/components/auth/login-page.component.html b/src/Squidex/app/components/auth/login-page.component.html new file mode 100644 index 000000000..8d2d3f655 --- /dev/null +++ b/src/Squidex/app/components/auth/login-page.component.html @@ -0,0 +1,5 @@ +
+
+ Failed to login +
+
\ No newline at end of file diff --git a/src/Squidex/app/components/auth/login-page.component.ts b/src/Squidex/app/components/auth/login-page.component.ts new file mode 100644 index 000000000..552fe816b --- /dev/null +++ b/src/Squidex/app/components/auth/login-page.component.ts @@ -0,0 +1,38 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Ng2 from '@angular/core'; +import * as Ng2Router from '@angular/router'; + +import { AuthService } from './../../shared'; + +@Ng2.Component({ + selector: 'login', + template: '' +}) +export class LoginPageComponent implements Ng2.OnInit { + public showError = false; + + constructor( + private readonly authService: AuthService, + private readonly router: Ng2Router.Router + ) { + } + + public ngOnInit() { + this.authService.loginComplete().subscribe( + () => { + debugger; + this.router.navigate(['/']); + }, + e => { + debugger; + this.showError = true; + } + ); + } +} \ No newline at end of file diff --git a/src/Squidex/app/components/auth/logout-page.component.html b/src/Squidex/app/components/auth/logout-page.component.html new file mode 100644 index 000000000..8d2d3f655 --- /dev/null +++ b/src/Squidex/app/components/auth/logout-page.component.html @@ -0,0 +1,5 @@ +
+
+ Failed to login +
+
\ No newline at end of file diff --git a/src/Squidex/app/components/login/login-page.component.ts b/src/Squidex/app/components/auth/logout-page.component.ts similarity index 62% rename from src/Squidex/app/components/login/login-page.component.ts rename to src/Squidex/app/components/auth/logout-page.component.ts index d569945bf..37eb393e2 100644 --- a/src/Squidex/app/components/login/login-page.component.ts +++ b/src/Squidex/app/components/auth/logout-page.component.ts @@ -6,27 +6,27 @@ */ import * as Ng2 from '@angular/core'; -import * as Ng2Common from '@angular/common'; +import * as Ng2Router from '@angular/router'; import { AuthService } from './../../shared'; @Ng2.Component({ - selector: 'login', - template + selector: 'logout', + template: '' }) -export class LoginPageComponent implements Ng2.OnInit { +export class LogoutPageComponent implements Ng2.OnInit { public showFailedError = false; constructor( private readonly authService: AuthService, - private readonly location: Ng2Common.Location + private readonly router: Ng2Router.Router ) { } public ngOnInit() { - this.authService.login().subscribe( + this.authService.logoutComplete().subscribe( () => { - this.location.back(); + this.router.navigate(['/']); }, () => { this.showFailedError = true; diff --git a/src/Squidex/app/components/index.ts b/src/Squidex/app/components/index.ts index 61702b4e3..b17807a2d 100644 --- a/src/Squidex/app/components/index.ts +++ b/src/Squidex/app/components/index.ts @@ -6,5 +6,5 @@ */ export * from './apps'; -export * from './layout'; -export * from './login'; \ No newline at end of file +export * from './auth'; +export * from './layout'; \ No newline at end of file diff --git a/src/Squidex/app/components/login/login-page.component.html b/src/Squidex/app/components/login/login-page.component.html deleted file mode 100644 index 27df9f084..000000000 --- a/src/Squidex/app/components/login/login-page.component.html +++ /dev/null @@ -1,3 +0,0 @@ -
- Logging in -
\ No newline at end of file diff --git a/src/Squidex/app/shared/guards/auth.guard.ts b/src/Squidex/app/shared/guards/auth.guard.ts index 58d39d805..de1bc5f92 100644 --- a/src/Squidex/app/shared/guards/auth.guard.ts +++ b/src/Squidex/app/shared/guards/auth.guard.ts @@ -9,29 +9,22 @@ import * as Ng2 from '@angular/core'; import * as Ng2Router from '@angular/router'; import { AuthService } from './../services/auth.service'; - -const LOGIN_URL = '/login/'; @Ng2.Injectable() export class AuthGuard implements Ng2Router.CanActivate { constructor( - private readonly router: Ng2Router.Router, private readonly authService: AuthService ) { } public canActivate(route: Ng2Router.ActivatedRouteSnapshot, state: Ng2Router.RouterStateSnapshot): Promise | boolean { - if (state.url !== LOGIN_URL) { - return this.authService.checkLogin().then(isAuthenticated => { - if (!isAuthenticated) { - this.router.navigate([LOGIN_URL]); - - return false; - } - return true; - }); - } + return this.authService.checkLogin().then(isAuthenticated => { + if (!isAuthenticated) { + this.authService.login(); - return true; + return false; + } + return true; + }); } } \ No newline at end of file diff --git a/src/Squidex/app/shared/services/auth.service.ts b/src/Squidex/app/shared/services/auth.service.ts index 6a03d0f3c..258193ebf 100644 --- a/src/Squidex/app/shared/services/auth.service.ts +++ b/src/Squidex/app/shared/services/auth.service.ts @@ -7,6 +7,7 @@ import * as Ng2 from '@angular/core'; import * as Ng2Http from '@angular/http'; +import * as Ng2Router from '@angular/router'; import { Log, @@ -38,19 +39,21 @@ export class AuthService { } constructor(apiUrl: ApiUrlConfig, - private readonly http: Ng2Http.Http, + private readonly http: Ng2Http.Http ) { Log.logger = console; if (apiUrl) { this.userManager = new UserManager({ - client_id: 'squidex-frontend', - scope: 'squidex-api openid profile ', - response_type: 'id_token token', - silent_redirect_uri: apiUrl.buildUrl('identity-server/client-callback-silent/'), - popup_redirect_uri: apiUrl.buildUrl('identity-server/client-callback-popup/'), - authority: apiUrl.buildUrl('identity-server/'), - automaticSilentRenew: true + client_id: 'squidex-frontend', + scope: 'squidex-api openid profile ', + response_type: 'id_token token', + redirect_uri: apiUrl.buildUrl('/login;'), + post_logout_redirect_uri: apiUrl.buildUrl('/logout;'), + silent_redirect_uri: apiUrl.buildUrl('identity-server/client-callback-silent/'), + popup_redirect_uri: apiUrl.buildUrl('identity-server/client-callback-popup/'), + authority: apiUrl.buildUrl('identity-server/'), + automaticSilentRenew: true }); this.userManager.events.addUserLoaded(user => { @@ -82,17 +85,19 @@ export class AuthService { } public logout(): Observable { + return Observable.fromPromise(this.userManager.signoutRedirect()); + } + + public logoutComplete(): Observable { return Observable.fromPromise(this.userManager.signoutRedirectCallback()); } - public login(): Observable { - const userPromise = - this.checkState(this.userManager.signinSilent()) - .then(result => { - return result || this.checkState(this.userManager.signinPopup()); - }); + public login(): Observable { + return Observable.fromPromise(this.userManager.signinRedirect()); + } - return Observable.fromPromise(userPromise); + public loginComplete(): Observable { + return Observable.fromPromise(this.userManager.signinRedirectCallback()); } private onAuthenticated(user: User) {