diff --git a/src/Angular-CSharp.csproj.in b/src/Angular-CSharp.csproj.in index 67b90704..3d4337fa 100644 --- a/src/Angular-CSharp.csproj.in +++ b/src/Angular-CSharp.csproj.in @@ -16,7 +16,6 @@ - diff --git a/src/content/Angular-CSharp/.template.config/template.json b/src/content/Angular-CSharp/.template.config/template.json index df06f71a..cbda891e 100644 --- a/src/content/Angular-CSharp/.template.config/template.json +++ b/src/content/Angular-CSharp/.template.config/template.json @@ -50,9 +50,7 @@ "exclude": [ "Pages/Shared/_LoginPartial.cshtml", "Data/**", - "Models/**", - "ClientApp/src/api-authorization/**", - "Controllers/OidcConfigurationController.cs" + "Models/**" ] }, { diff --git a/src/content/Angular-CSharp/ClientApp/proxy.conf.js b/src/content/Angular-CSharp/ClientApp/proxy.conf.js index cf248f61..aed376f7 100644 --- a/src/content/Angular-CSharp/ClientApp/proxy.conf.js +++ b/src/content/Angular-CSharp/ClientApp/proxy.conf.js @@ -1,7 +1,7 @@ const { env } = require('process'); const target = env.ASPNETCORE_HTTPS_PORT ? `https://localhost:${env.ASPNETCORE_HTTPS_PORT}` : - env.ASPNETCORE_URLS ? env.ASPNETCORE_URLS.split(';')[0] : 'http://localhost:8080'; + env.ASPNETCORE_URLS ? env.ASPNETCORE_URLS.split(';')[0] : 'http://localhost:5001'; const PROXY_CONFIG = [ { diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/api-authorization.constants.ts b/src/content/Angular-CSharp/ClientApp/src/api-authorization/api-authorization.constants.ts deleted file mode 100644 index 4a52fdee..00000000 --- a/src/content/Angular-CSharp/ClientApp/src/api-authorization/api-authorization.constants.ts +++ /dev/null @@ -1,81 +0,0 @@ -export const ApplicationName = 'Company.WebApplication1'; - -export const ReturnUrlType = 'returnUrl'; - -export const QueryParameterNames = { - ReturnUrl: ReturnUrlType, - Message: 'message' -}; - -export const LogoutActions = { - LogoutCallback: 'logout-callback', - Logout: 'logout', - LoggedOut: 'logged-out' -}; - -export const LoginActions = { - Login: 'login', - LoginCallback: 'login-callback', - LoginFailed: 'login-failed', - Profile: 'profile', - Register: 'register' -}; - -let applicationPaths: ApplicationPathsType = { - DefaultLoginRedirectPath: '/', - ApiAuthorizationClientConfigurationUrl: `_configuration/${ApplicationName}`, - Login: `authentication/${LoginActions.Login}`, - LoginFailed: `authentication/${LoginActions.LoginFailed}`, - LoginCallback: `authentication/${LoginActions.LoginCallback}`, - Register: `authentication/${LoginActions.Register}`, - Profile: `authentication/${LoginActions.Profile}`, - LogOut: `authentication/${LogoutActions.Logout}`, - LoggedOut: `authentication/${LogoutActions.LoggedOut}`, - LogOutCallback: `authentication/${LogoutActions.LogoutCallback}`, - LoginPathComponents: [], - LoginFailedPathComponents: [], - LoginCallbackPathComponents: [], - RegisterPathComponents: [], - ProfilePathComponents: [], - LogOutPathComponents: [], - LoggedOutPathComponents: [], - LogOutCallbackPathComponents: [], - IdentityRegisterPath: 'Identity/Account/Register', - IdentityManagePath: 'Identity/Account/Manage' -}; - -applicationPaths = { - ...applicationPaths, - LoginPathComponents: applicationPaths.Login.split('/'), - LoginFailedPathComponents: applicationPaths.LoginFailed.split('/'), - RegisterPathComponents: applicationPaths.Register.split('/'), - ProfilePathComponents: applicationPaths.Profile.split('/'), - LogOutPathComponents: applicationPaths.LogOut.split('/'), - LoggedOutPathComponents: applicationPaths.LoggedOut.split('/'), - LogOutCallbackPathComponents: applicationPaths.LogOutCallback.split('/') -}; - -interface ApplicationPathsType { - readonly DefaultLoginRedirectPath: string; - readonly ApiAuthorizationClientConfigurationUrl: string; - readonly Login: string; - readonly LoginFailed: string; - readonly LoginCallback: string; - readonly Register: string; - readonly Profile: string; - readonly LogOut: string; - readonly LoggedOut: string; - readonly LogOutCallback: string; - readonly LoginPathComponents: string []; - readonly LoginFailedPathComponents: string []; - readonly LoginCallbackPathComponents: string []; - readonly RegisterPathComponents: string []; - readonly ProfilePathComponents: string []; - readonly LogOutPathComponents: string []; - readonly LoggedOutPathComponents: string []; - readonly LogOutCallbackPathComponents: string []; - readonly IdentityRegisterPath: string; - readonly IdentityManagePath: string; -} - -export const ApplicationPaths: ApplicationPathsType = applicationPaths; diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/api-authorization.module.spec.ts b/src/content/Angular-CSharp/ClientApp/src/api-authorization/api-authorization.module.spec.ts deleted file mode 100644 index f6a4b290..00000000 --- a/src/content/Angular-CSharp/ClientApp/src/api-authorization/api-authorization.module.spec.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ApiAuthorizationModule } from './api-authorization.module'; - -describe('ApiAuthorizationModule', () => { - let apiAuthorizationModule: ApiAuthorizationModule; - - beforeEach(() => { - apiAuthorizationModule = new ApiAuthorizationModule(); - }); - - it('should create an instance', () => { - expect(apiAuthorizationModule).toBeTruthy(); - }); -}); diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/api-authorization.module.ts b/src/content/Angular-CSharp/ClientApp/src/api-authorization/api-authorization.module.ts deleted file mode 100644 index 9929b339..00000000 --- a/src/content/Angular-CSharp/ClientApp/src/api-authorization/api-authorization.module.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { LoginMenuComponent } from './login-menu/login-menu.component'; -import { LoginComponent } from './login/login.component'; -import { LogoutComponent } from './logout/logout.component'; -import { RouterModule } from '@angular/router'; -import { ApplicationPaths } from './api-authorization.constants'; -import { HttpClientModule } from '@angular/common/http'; - -@NgModule({ - imports: [ - CommonModule, - HttpClientModule, - RouterModule.forChild( - [ - { path: ApplicationPaths.Register, component: LoginComponent }, - { path: ApplicationPaths.Profile, component: LoginComponent }, - { path: ApplicationPaths.Login, component: LoginComponent }, - { path: ApplicationPaths.LoginFailed, component: LoginComponent }, - { path: ApplicationPaths.LoginCallback, component: LoginComponent }, - { path: ApplicationPaths.LogOut, component: LogoutComponent }, - { path: ApplicationPaths.LoggedOut, component: LogoutComponent }, - { path: ApplicationPaths.LogOutCallback, component: LogoutComponent } - ] - ) - ], - declarations: [LoginMenuComponent, LoginComponent, LogoutComponent], - exports: [LoginMenuComponent, LoginComponent, LogoutComponent] -}) -export class ApiAuthorizationModule { } diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.guard.spec.ts b/src/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.guard.spec.ts deleted file mode 100644 index 3e9549af..00000000 --- a/src/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.guard.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed, inject } from '@angular/core/testing'; -import { RouterTestingModule } from '@angular/router/testing'; -import { AuthorizeGuard } from './authorize.guard'; - -describe('AuthorizeGuard', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [RouterTestingModule], - providers: [AuthorizeGuard] - }); - }); - - it('should ...', inject([AuthorizeGuard], (guard: AuthorizeGuard) => { - expect(guard).toBeTruthy(); - })); -}); diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.guard.ts b/src/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.guard.ts deleted file mode 100644 index 690fdd95..00000000 --- a/src/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.guard.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Injectable } from '@angular/core'; -import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router'; -import { Observable } from 'rxjs'; -import { AuthorizeService } from './authorize.service'; -import { tap } from 'rxjs/operators'; -import { ApplicationPaths, QueryParameterNames } from './api-authorization.constants'; - -@Injectable({ - providedIn: 'root' -}) -export class AuthorizeGuard implements CanActivate { - constructor(private authorize: AuthorizeService, private router: Router) { - } - canActivate( - _next: ActivatedRouteSnapshot, - state: RouterStateSnapshot): Observable | Promise | boolean { - return this.authorize.isAuthenticated() - .pipe(tap(isAuthenticated => this.handleAuthorization(isAuthenticated, state))); - } - - private handleAuthorization(isAuthenticated: boolean, state: RouterStateSnapshot) { - if (!isAuthenticated) { - this.router.navigate(ApplicationPaths.LoginPathComponents, { - queryParams: { - [QueryParameterNames.ReturnUrl]: state.url - } - }); - } - } -} diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.interceptor.spec.ts b/src/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.interceptor.spec.ts deleted file mode 100644 index a97ac0a0..00000000 --- a/src/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.interceptor.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { TestBed, inject } from '@angular/core/testing'; - -import { AuthorizeInterceptor } from './authorize.interceptor'; - -describe('AuthorizeInterceptor', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [AuthorizeInterceptor] - }); - }); - - it('should be created', inject([AuthorizeInterceptor], (service: AuthorizeInterceptor) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.interceptor.ts b/src/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.interceptor.ts deleted file mode 100644 index 6e23db7b..00000000 --- a/src/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.interceptor.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Injectable } from '@angular/core'; -import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http'; -import { Observable } from 'rxjs'; -import { AuthorizeService } from './authorize.service'; -import { mergeMap } from 'rxjs/operators'; - -@Injectable({ - providedIn: 'root' -}) -export class AuthorizeInterceptor implements HttpInterceptor { - constructor(private authorize: AuthorizeService) { } - - intercept(req: HttpRequest, next: HttpHandler): Observable> { - return this.authorize.getAccessToken() - .pipe(mergeMap(token => this.processRequestWithToken(token, req, next))); - } - - // Checks if there is an access_token available in the authorize service - // and adds it to the request in case it's targeted at the same origin as the - // single page application. - private processRequestWithToken(token: string | null, req: HttpRequest, next: HttpHandler) { - if (!!token && this.isSameOriginUrl(req)) { - req = req.clone({ - setHeaders: { - Authorization: `Bearer ${token}` - } - }); - } - - return next.handle(req); - } - - private isSameOriginUrl(req: any) { - // It's an absolute url with the same origin. - if (req.url.startsWith(`${window.location.origin}/`)) { - return true; - } - - // It's a protocol relative url with the same origin. - // For example: //www.example.com/api/Products - if (req.url.startsWith(`//${window.location.host}/`)) { - return true; - } - - // It's a relative url like /api/Products - if (/^\/[^\/].*/.test(req.url)) { - return true; - } - - // It's an absolute or protocol relative url that - // doesn't have the same origin. - return false; - } -} diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.service.spec.ts b/src/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.service.spec.ts deleted file mode 100644 index 41c9d65e..00000000 --- a/src/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.service.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { TestBed, inject } from '@angular/core/testing'; - -import { AuthorizeService } from './authorize.service'; - -describe('AuthorizeService', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [AuthorizeService] - }); - }); - - it('should be created', inject([AuthorizeService], (service: AuthorizeService) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.service.ts b/src/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.service.ts deleted file mode 100644 index d318026f..00000000 --- a/src/content/Angular-CSharp/ClientApp/src/api-authorization/authorize.service.ts +++ /dev/null @@ -1,201 +0,0 @@ -import { Injectable } from '@angular/core'; -import { User, UserManager } from 'oidc-client'; -import { BehaviorSubject, concat, from, Observable } from 'rxjs'; -import { filter, map, mergeMap, take, tap } from 'rxjs/operators'; -import { ApplicationPaths, ApplicationName } from './api-authorization.constants'; - -export type IAuthenticationResult = - SuccessAuthenticationResult | - FailureAuthenticationResult | - RedirectAuthenticationResult; - -export interface SuccessAuthenticationResult { - status: AuthenticationResultStatus.Success; - state: any; -} - -export interface FailureAuthenticationResult { - status: AuthenticationResultStatus.Fail; - message: string; -} - -export interface RedirectAuthenticationResult { - status: AuthenticationResultStatus.Redirect; -} - -export enum AuthenticationResultStatus { - Success, - Redirect, - Fail -} - -export interface IUser { - name?: string; -} - -@Injectable({ - providedIn: 'root' -}) -export class AuthorizeService { - // By default pop ups are disabled because they don't work properly on Edge. - // If you want to enable pop up authentication simply set this flag to false. - - private popUpDisabled = true; - private userManager?: UserManager; - private userSubject: BehaviorSubject = new BehaviorSubject(null); - - public isAuthenticated(): Observable { - return this.getUser().pipe(map(u => !!u)); - } - - public getUser(): Observable { - return concat( - this.userSubject.pipe(take(1), filter(u => !!u)), - this.getUserFromStorage().pipe(filter(u => !!u), tap(u => this.userSubject.next(u))), - this.userSubject.asObservable()); - } - - public getAccessToken(): Observable { - return from(this.ensureUserManagerInitialized()) - .pipe(mergeMap(() => from(this.userManager!.getUser())), - map(user => user && user.access_token)); - } - - // We try to authenticate the user in three different ways: - // 1) We try to see if we can authenticate the user silently. This happens - // when the user is already logged in on the IdP and is done using a hidden iframe - // on the client. - // 2) We try to authenticate the user using a PopUp Window. This might fail if there is a - // Pop-Up blocker or the user has disabled PopUps. - // 3) If the two methods above fail, we redirect the browser to the IdP to perform a traditional - // redirect flow. - public async signIn(state: any): Promise { - await this.ensureUserManagerInitialized(); - let user: User | null = null; - try { - user = await this.userManager!.signinSilent(this.createArguments()); - this.userSubject.next(user.profile); - return this.success(state); - } catch (silentError) { - // User might not be authenticated, fallback to popup authentication - console.log('Silent authentication error: ', silentError); - - try { - if (this.popUpDisabled) { - throw new Error('Popup disabled. Change \'authorize.service.ts:AuthorizeService.popupDisabled\' to false to enable it.'); - } - user = await this.userManager!.signinPopup(this.createArguments()); - this.userSubject.next(user.profile); - return this.success(state); - } catch (popupError: any) { - if (popupError.message === 'Popup window closed') { - // The user explicitly cancelled the login action by closing an opened popup. - return this.error('The user closed the window.'); - } else if (!this.popUpDisabled) { - console.log('Popup authentication error: ', popupError); - } - - // PopUps might be blocked by the user, fallback to redirect - try { - await this.userManager!.signinRedirect(this.createArguments(state)); - return this.redirect(); - } catch (redirectError: any) { - console.log('Redirect authentication error: ', redirectError); - return this.error(redirectError); - } - } - } - } - - public async completeSignIn(url: string): Promise { - try { - await this.ensureUserManagerInitialized(); - const user = await this.userManager!.signinCallback(url); - this.userSubject.next(user && user.profile); - return this.success(user && user.state); - } catch (error) { - console.log('There was an error signing in: ', error); - return this.error('There was an error signing in.'); - } - } - - public async signOut(state: any): Promise { - try { - if (this.popUpDisabled) { - throw new Error('Popup disabled. Change \'authorize.service.ts:AuthorizeService.popupDisabled\' to false to enable it.'); - } - - await this.ensureUserManagerInitialized(); - await this.userManager!.signoutPopup(this.createArguments()); - this.userSubject.next(null); - return this.success(state); - } catch (popupSignOutError: any) { - console.log('Popup signout error: ', popupSignOutError); - try { - await this.userManager!.signoutRedirect(this.createArguments(state)); - return this.redirect(); - } catch (redirectSignOutError: any) { - console.log('Redirect signout error: ', redirectSignOutError); - return this.error(redirectSignOutError); - } - } - } - - public async completeSignOut(url: string): Promise { - await this.ensureUserManagerInitialized(); - try { - const response = await this.userManager!.signoutCallback(url); - this.userSubject.next(null); - return this.success(response && response.state); - } catch (error: any) { - console.log(`There was an error trying to log out '${error}'.`); - return this.error(error); - } - } - - private createArguments(state?: any): any { - return { useReplaceToNavigate: true, data: state }; - } - - private error(message: string): IAuthenticationResult { - return { status: AuthenticationResultStatus.Fail, message }; - } - - private success(state: any): IAuthenticationResult { - return { status: AuthenticationResultStatus.Success, state }; - } - - private redirect(): IAuthenticationResult { - return { status: AuthenticationResultStatus.Redirect }; - } - - private async ensureUserManagerInitialized(): Promise { - this.userManager ??= await this.createUserManager(); - } - - private async createUserManager(): Promise { - const response = await fetch(ApplicationPaths.ApiAuthorizationClientConfigurationUrl); - if (!response.ok) { - throw new Error(`Could not load settings for '${ApplicationName}'`); - } - - const settings: any = await response.json(); - settings.automaticSilentRenew = true; - settings.includeIdTokenInSilentRenew = true; - const userManager = new UserManager(settings); - - userManager.events.addUserSignedOut(async () => { - await this.userManager!.removeUser(); - this.userSubject.next(null); - }); - - return userManager; - } - - private getUserFromStorage(): Observable { - return from(this.ensureUserManagerInitialized()) - .pipe( - mergeMap(() => this.userManager!.getUser()), - map(u => u && u.profile)); - } -} diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/login-menu/login-menu.component.css b/src/content/Angular-CSharp/ClientApp/src/api-authorization/login-menu/login-menu.component.css deleted file mode 100644 index e69de29b..00000000 diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/login-menu/login-menu.component.html b/src/content/Angular-CSharp/ClientApp/src/api-authorization/login-menu/login-menu.component.html deleted file mode 100644 index 27f88793..00000000 --- a/src/content/Angular-CSharp/ClientApp/src/api-authorization/login-menu/login-menu.component.html +++ /dev/null @@ -1,16 +0,0 @@ - - diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/login-menu/login-menu.component.spec.ts b/src/content/Angular-CSharp/ClientApp/src/api-authorization/login-menu/login-menu.component.spec.ts deleted file mode 100644 index 48ce750f..00000000 --- a/src/content/Angular-CSharp/ClientApp/src/api-authorization/login-menu/login-menu.component.spec.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { RouterTestingModule } from '@angular/router/testing'; -import { LoginMenuComponent } from './login-menu.component'; -import { AuthorizeService } from '../authorize.service'; -import { of } from 'rxjs'; - -describe('LoginMenuComponent', () => { - let component: LoginMenuComponent; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [RouterTestingModule], - declarations: [ LoginMenuComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - let authService = TestBed.inject(AuthorizeService); - - spyOn(authService as any, 'createUserManager').and.callFake(() => { - const userManager = jasmine.createSpyObj([]); - return Promise.resolve(userManager); - }); - spyOn(authService as any, 'getUserFromStorage').and.returnValue( - of(null)); - - fixture = TestBed.createComponent(LoginMenuComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/login-menu/login-menu.component.ts b/src/content/Angular-CSharp/ClientApp/src/api-authorization/login-menu/login-menu.component.ts deleted file mode 100644 index 946a5294..00000000 --- a/src/content/Angular-CSharp/ClientApp/src/api-authorization/login-menu/login-menu.component.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { AuthorizeService } from '../authorize.service'; -import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; - -@Component({ - selector: 'app-login-menu', - templateUrl: './login-menu.component.html', - styleUrls: ['./login-menu.component.css'] -}) -export class LoginMenuComponent implements OnInit { - public isAuthenticated?: Observable; - public userName?: Observable; - - constructor(private authorizeService: AuthorizeService) { } - - ngOnInit() { - this.isAuthenticated = this.authorizeService.isAuthenticated(); - this.userName = this.authorizeService.getUser().pipe(map(u => u && u.name)); - } -} diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/login/login.component.css b/src/content/Angular-CSharp/ClientApp/src/api-authorization/login/login.component.css deleted file mode 100644 index e69de29b..00000000 diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/login/login.component.html b/src/content/Angular-CSharp/ClientApp/src/api-authorization/login/login.component.html deleted file mode 100644 index 5b5e4e40..00000000 --- a/src/content/Angular-CSharp/ClientApp/src/api-authorization/login/login.component.html +++ /dev/null @@ -1 +0,0 @@ -

{{ message | async }}

\ No newline at end of file diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/login/login.component.spec.ts b/src/content/Angular-CSharp/ClientApp/src/api-authorization/login/login.component.spec.ts deleted file mode 100644 index 53958256..00000000 --- a/src/content/Angular-CSharp/ClientApp/src/api-authorization/login/login.component.spec.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { RouterTestingModule } from '@angular/router/testing'; -import { LoginComponent } from './login.component'; -import { ActivatedRoute, UrlSegment, convertToParamMap, Params, Router } from '@angular/router'; -import { LoginActions } from '../api-authorization.constants'; -import { AuthorizeService } from '../authorize.service'; -import { HomeComponent } from 'src/app/home/home.component'; - -describe('LoginComponent', () => { - let component: LoginComponent; - let fixture: ComponentFixture; - let router: Router; - - beforeEach(() => { - let tempParams: Params = { id: '1234' }; - - let segment0: UrlSegment = new UrlSegment('segment0', {}); - let segment1: UrlSegment = new UrlSegment(LoginActions.Login, {}); - - let urlSegments: UrlSegment[] = [segment0, segment1]; - - TestBed.configureTestingModule({ - imports: [ - RouterTestingModule.withRoutes([ - { path: 'authentication/login-failed', component: HomeComponent } - ])], - declarations: [LoginComponent, HomeComponent], - providers: [{ - provide: ActivatedRoute, useValue: { - snapshot: { - paramMap: convertToParamMap(tempParams), - url: urlSegments, - queryParams: tempParams - } - } - }] - }).compileComponents(); - - router = TestBed.inject(Router); - spyOn(router, 'navigate').and.returnValue(Promise.resolve(true)); - }); - - beforeEach(() => { - let authService = TestBed.inject(AuthorizeService); - - spyOn(authService as any, 'createUserManager').and.callFake(() => { - const userManager = jasmine.createSpyObj([]); - return Promise.resolve(userManager); - }) - - fixture = TestBed.createComponent(LoginComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/login/login.component.ts b/src/content/Angular-CSharp/ClientApp/src/api-authorization/login/login.component.ts deleted file mode 100644 index 3d520708..00000000 --- a/src/content/Angular-CSharp/ClientApp/src/api-authorization/login/login.component.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { AuthorizeService, AuthenticationResultStatus } from '../authorize.service'; -import { ActivatedRoute, Router } from '@angular/router'; -import { BehaviorSubject } from 'rxjs'; -import { LoginActions, QueryParameterNames, ApplicationPaths, ReturnUrlType } from '../api-authorization.constants'; - -// The main responsibility of this component is to handle the user's login process. -// This is the starting point for the login process. Any component that needs to authenticate -// a user can simply perform a redirect to this component with a returnUrl query parameter and -// let the component perform the login and return back to the return url. -@Component({ - selector: 'app-login', - templateUrl: './login.component.html', - styleUrls: ['./login.component.css'] -}) -export class LoginComponent implements OnInit { - public message = new BehaviorSubject(null); - - constructor( - private authorizeService: AuthorizeService, - private activatedRoute: ActivatedRoute, - private router: Router) { } - - async ngOnInit() { - const action = this.activatedRoute.snapshot.url[1]; - switch (action.path) { - case LoginActions.Login: - await this.login(this.getReturnUrl()); - break; - case LoginActions.LoginCallback: - await this.processLoginCallback(); - break; - case LoginActions.LoginFailed: - const message = this.activatedRoute.snapshot.queryParamMap.get(QueryParameterNames.Message); - this.message.next(message); - break; - case LoginActions.Profile: - this.redirectToProfile(); - break; - case LoginActions.Register: - this.redirectToRegister(); - break; - default: - throw new Error(`Invalid action '${action}'`); - } - } - - - private async login(returnUrl: string): Promise { - const state: INavigationState = { returnUrl }; - const result = await this.authorizeService.signIn(state); - this.message.next(undefined); - switch (result.status) { - case AuthenticationResultStatus.Redirect: - break; - case AuthenticationResultStatus.Success: - await this.navigateToReturnUrl(returnUrl); - break; - case AuthenticationResultStatus.Fail: - await this.router.navigate(ApplicationPaths.LoginFailedPathComponents, { - queryParams: { [QueryParameterNames.Message]: result.message } - }); - break; - default: - throw new Error(`Invalid status result ${(result as any).status}.`); - } - } - - private async processLoginCallback(): Promise { - const url = window.location.href; - const result = await this.authorizeService.completeSignIn(url); - switch (result.status) { - case AuthenticationResultStatus.Redirect: - // There should not be any redirects as completeSignIn never redirects. - throw new Error('Should not redirect.'); - case AuthenticationResultStatus.Success: - await this.navigateToReturnUrl(this.getReturnUrl(result.state)); - break; - case AuthenticationResultStatus.Fail: - this.message.next(result.message); - break; - } - } - - private redirectToRegister(): any { - this.redirectToApiAuthorizationPath( - `${ApplicationPaths.IdentityRegisterPath}?returnUrl=${encodeURI('/' + ApplicationPaths.Login)}`); - } - - private redirectToProfile(): void { - this.redirectToApiAuthorizationPath(ApplicationPaths.IdentityManagePath); - } - - private async navigateToReturnUrl(returnUrl: string) { - // It's important that we do a replace here so that we remove the callback uri with the - // fragment containing the tokens from the browser history. - await this.router.navigateByUrl(returnUrl, { - replaceUrl: true - }); - } - - private getReturnUrl(state?: INavigationState): string { - const fromQuery = (this.activatedRoute.snapshot.queryParams as INavigationState).returnUrl; - // If the url is coming from the query string, check that is either - // a relative url or an absolute url - if (fromQuery && - !(fromQuery.startsWith(`${window.location.origin}/`) || - /\/[^\/].*/.test(fromQuery))) { - // This is an extra check to prevent open redirects. - throw new Error('Invalid return url. The return url needs to have the same origin as the current page.'); - } - return (state && state.returnUrl) || - fromQuery || - ApplicationPaths.DefaultLoginRedirectPath; - } - - private redirectToApiAuthorizationPath(apiAuthorizationPath: string) { - // It's important that we do a replace here so that when the user hits the back arrow on the - // browser they get sent back to where it was on the app instead of to an endpoint on this - // component. - const redirectUrl = `${window.location.origin}/${apiAuthorizationPath}`; - window.location.replace(redirectUrl); - } -} - -interface INavigationState { - [ReturnUrlType]: string; -} diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/logout/logout.component.css b/src/content/Angular-CSharp/ClientApp/src/api-authorization/logout/logout.component.css deleted file mode 100644 index e69de29b..00000000 diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/logout/logout.component.html b/src/content/Angular-CSharp/ClientApp/src/api-authorization/logout/logout.component.html deleted file mode 100644 index 5b5e4e40..00000000 --- a/src/content/Angular-CSharp/ClientApp/src/api-authorization/logout/logout.component.html +++ /dev/null @@ -1 +0,0 @@ -

{{ message | async }}

\ No newline at end of file diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/logout/logout.component.spec.ts b/src/content/Angular-CSharp/ClientApp/src/api-authorization/logout/logout.component.spec.ts deleted file mode 100644 index ef77791d..00000000 --- a/src/content/Angular-CSharp/ClientApp/src/api-authorization/logout/logout.component.spec.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { RouterTestingModule } from '@angular/router/testing'; -import { LogoutComponent } from './logout.component'; -import { HomeComponent } from 'src/app/home/home.component'; -import { ActivatedRoute, convertToParamMap, Params, UrlSegment } from '@angular/router'; -import { LogoutActions } from '../api-authorization.constants'; - -describe('LogoutComponent', () => { - let component: LogoutComponent; - let fixture: ComponentFixture; - - beforeEach(async(() => { - let tempParams: Params = { id: '1234' }; - - let segment0: UrlSegment = new UrlSegment('segment0', {}); - let segment1: UrlSegment = new UrlSegment(LogoutActions.LoggedOut, {}); - - let urlSegments: UrlSegment[] = [segment0, segment1]; - - TestBed.configureTestingModule({ - imports: [ - RouterTestingModule.withRoutes([ - { path: 'authentication/login-failed', component: HomeComponent } - ])], - declarations: [LogoutComponent, HomeComponent], - providers: [{ - provide: ActivatedRoute, useValue: { - snapshot: { - paramMap: convertToParamMap(tempParams), - url: urlSegments, - queryParams: tempParams - } - } - }] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(LogoutComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/content/Angular-CSharp/ClientApp/src/api-authorization/logout/logout.component.ts b/src/content/Angular-CSharp/ClientApp/src/api-authorization/logout/logout.component.ts deleted file mode 100644 index 61455c8f..00000000 --- a/src/content/Angular-CSharp/ClientApp/src/api-authorization/logout/logout.component.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { AuthenticationResultStatus, AuthorizeService } from '../authorize.service'; -import { BehaviorSubject } from 'rxjs'; -import { ActivatedRoute, Router } from '@angular/router'; -import { take } from 'rxjs/operators'; -import { LogoutActions, ApplicationPaths, ReturnUrlType } from '../api-authorization.constants'; - -// The main responsibility of this component is to handle the user's logout process. -// This is the starting point for the logout process, which is usually initiated when a -// user clicks on the logout button on the LoginMenu component. -@Component({ - selector: 'app-logout', - templateUrl: './logout.component.html', - styleUrls: ['./logout.component.css'] -}) -export class LogoutComponent implements OnInit { - public message = new BehaviorSubject(null); - - constructor( - private authorizeService: AuthorizeService, - private activatedRoute: ActivatedRoute, - private router: Router) { } - - async ngOnInit() { - const action = this.activatedRoute.snapshot.url[1]; - switch (action.path) { - case LogoutActions.Logout: - if (!!window.history.state.local) { - await this.logout(this.getReturnUrl()); - } else { - // This prevents regular links to /authentication/logout from triggering a logout - this.message.next('The logout was not initiated from within the page.'); - } - - break; - case LogoutActions.LogoutCallback: - await this.processLogoutCallback(); - break; - case LogoutActions.LoggedOut: - this.message.next('You successfully logged out!'); - break; - default: - throw new Error(`Invalid action '${action}'`); - } - } - - private async logout(returnUrl: string): Promise { - const state: INavigationState = { returnUrl }; - const isauthenticated = await this.authorizeService.isAuthenticated().pipe( - take(1) - ).toPromise(); - if (isauthenticated) { - const result = await this.authorizeService.signOut(state); - switch (result.status) { - case AuthenticationResultStatus.Redirect: - break; - case AuthenticationResultStatus.Success: - await this.navigateToReturnUrl(returnUrl); - break; - case AuthenticationResultStatus.Fail: - this.message.next(result.message); - break; - default: - throw new Error('Invalid authentication result status.'); - } - } else { - this.message.next('You successfully logged out!'); - } - } - - private async processLogoutCallback(): Promise { - const url = window.location.href; - const result = await this.authorizeService.completeSignOut(url); - switch (result.status) { - case AuthenticationResultStatus.Redirect: - // There should not be any redirects as the only time completeAuthentication finishes - // is when we are doing a redirect sign in flow. - throw new Error('Should not redirect.'); - case AuthenticationResultStatus.Success: - await this.navigateToReturnUrl(this.getReturnUrl(result.state)); - break; - case AuthenticationResultStatus.Fail: - this.message.next(result.message); - break; - default: - throw new Error('Invalid authentication result status.'); - } - } - - private async navigateToReturnUrl(returnUrl: string) { - await this.router.navigateByUrl(returnUrl, { - replaceUrl: true - }); - } - - private getReturnUrl(state?: INavigationState): string { - const fromQuery = (this.activatedRoute.snapshot.queryParams as INavigationState).returnUrl; - // If the url is coming from the query string, check that is either - // a relative url or an absolute url - if (fromQuery && - !(fromQuery.startsWith(`${window.location.origin}/`) || - /\/[^\/].*/.test(fromQuery))) { - // This is an extra check to prevent open redirects. - throw new Error('Invalid return url. The return url needs to have the same origin as the current page.'); - } - return (state && state.returnUrl) || - fromQuery || - ApplicationPaths.LoggedOut; - } -} - -interface INavigationState { - [ReturnUrlType]: string; -} diff --git a/src/content/Angular-CSharp/ClientApp/src/app/app.module.ts b/src/content/Angular-CSharp/ClientApp/src/app/app.module.ts index 679b31ce..5e415e67 100644 --- a/src/content/Angular-CSharp/ClientApp/src/app/app.module.ts +++ b/src/content/Angular-CSharp/ClientApp/src/app/app.module.ts @@ -1,11 +1,6 @@ import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; -////#if (IndividualLocalAuth) -import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; -////#else -import { HttpClientModule } from '@angular/common/http'; -////#endif import { RouterModule } from '@angular/router'; import { AppComponent } from './app.component'; @@ -13,11 +8,6 @@ import { NavMenuComponent } from './nav-menu/nav-menu.component'; import { HomeComponent } from './home/home.component'; import { CounterComponent } from './counter/counter.component'; import { FetchDataComponent } from './fetch-data/fetch-data.component'; -////#if (IndividualLocalAuth) -import { ApiAuthorizationModule } from 'src/api-authorization/api-authorization.module'; -import { AuthorizeGuard } from 'src/api-authorization/authorize.guard'; -import { AuthorizeInterceptor } from 'src/api-authorization/authorize.interceptor'; -////#endif @NgModule({ declarations: [ @@ -29,28 +19,14 @@ import { AuthorizeInterceptor } from 'src/api-authorization/authorize.intercepto ], imports: [ BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }), - HttpClientModule, FormsModule, - ////#if (IndividualLocalAuth) - ApiAuthorizationModule, - ////#endif RouterModule.forRoot([ { path: '', component: HomeComponent, pathMatch: 'full' }, { path: 'counter', component: CounterComponent }, - ////#if (IndividualLocalAuth) - { path: 'fetch-data', component: FetchDataComponent, canActivate: [AuthorizeGuard] }, - ////#else { path: 'fetch-data', component: FetchDataComponent }, - ////#endif ]) ], - ////#if (IndividualLocalAuth) - providers: [ - { provide: HTTP_INTERCEPTORS, useClass: AuthorizeInterceptor, multi: true } - ], - ////#else providers: [], - ////#endif bootstrap: [AppComponent] }) export class AppModule { } diff --git a/src/content/Angular-CSharp/ClientApp/src/app/fetch-data/fetch-data.component.ts b/src/content/Angular-CSharp/ClientApp/src/app/fetch-data/fetch-data.component.ts index a5b14777..e9c282e3 100644 --- a/src/content/Angular-CSharp/ClientApp/src/app/fetch-data/fetch-data.component.ts +++ b/src/content/Angular-CSharp/ClientApp/src/app/fetch-data/fetch-data.component.ts @@ -1,5 +1,4 @@ import { Component, Inject } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-fetch-data', @@ -8,8 +7,15 @@ import { HttpClient } from '@angular/common/http'; export class FetchDataComponent { public forecasts: WeatherForecast[] = []; - constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) { - http.get(baseUrl + 'weatherforecast').subscribe(result => { + constructor(@Inject('BASE_URL') baseUrl: string) { + fetch(baseUrl + 'weatherforecast').then(response => { +////#if (IndividualLocalAuth) + if (response.redirected && response.url.startsWith(`${baseUrl}Identity/Account/Login`)) { + window.location.href = `${baseUrl}Identity/Account/Login?ReturnUrl=/fetch-data`; + } +////#endif + return response.json(); + }).then(result => { this.forecasts = result; }, error => console.error(error)); } diff --git a/src/content/Angular-CSharp/ClientApp/src/app/nav-menu/nav-menu.component.html b/src/content/Angular-CSharp/ClientApp/src/app/nav-menu/nav-menu.component.html index 1b2e45ad..ef460662 100644 --- a/src/content/Angular-CSharp/ClientApp/src/app/nav-menu/nav-menu.component.html +++ b/src/content/Angular-CSharp/ClientApp/src/app/nav-menu/nav-menu.component.html @@ -37,10 +37,12 @@ >Fetch data + + + - - - diff --git a/src/content/Angular-CSharp/Controllers/OidcConfigurationController.cs b/src/content/Angular-CSharp/Controllers/OidcConfigurationController.cs deleted file mode 100644 index 96363797..00000000 --- a/src/content/Angular-CSharp/Controllers/OidcConfigurationController.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Microsoft.AspNetCore.ApiAuthorization.IdentityServer; -using Microsoft.AspNetCore.Mvc; - -namespace Company.WebApplication1.Controllers; - -public class OidcConfigurationController : Controller -{ - private readonly ILogger _logger; - - public OidcConfigurationController( - IClientRequestParametersProvider clientRequestParametersProvider, - ILogger logger) - { - ClientRequestParametersProvider = clientRequestParametersProvider; - _logger = logger; - } - - public IClientRequestParametersProvider ClientRequestParametersProvider { get; } - - [HttpGet("_configuration/{clientId}")] - public IActionResult GetClientRequestParameters([FromRoute]string clientId) - { - var parameters = ClientRequestParametersProvider.GetClientParameters(HttpContext, clientId); - return Ok(parameters); - } -} diff --git a/src/content/Angular-CSharp/Data/ApplicationDbContext.cs b/src/content/Angular-CSharp/Data/ApplicationDbContext.cs index 8d959d97..65b38517 100644 --- a/src/content/Angular-CSharp/Data/ApplicationDbContext.cs +++ b/src/content/Angular-CSharp/Data/ApplicationDbContext.cs @@ -1,16 +1,13 @@ -using Microsoft.AspNetCore.ApiAuthorization.IdentityServer; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Options; -using Duende.IdentityServer.EntityFramework.Options; using Company.WebApplication1.Models; namespace Company.WebApplication1.Data; -public class ApplicationDbContext : ApiAuthorizationDbContext +public class ApplicationDbContext : IdentityDbContext { - public ApplicationDbContext(DbContextOptions options, IOptions operationalStoreOptions) - : base(options, operationalStoreOptions) + public ApplicationDbContext(DbContextOptions options) + : base(options) { - } } diff --git a/src/content/Angular-CSharp/Data/SQLServer/00000000000000_CreateIdentitySchema.Designer.cs b/src/content/Angular-CSharp/Data/SQLServer/00000000000000_CreateIdentitySchema.Designer.cs index d0f2c771..451c9c2a 100644 --- a/src/content/Angular-CSharp/Data/SQLServer/00000000000000_CreateIdentitySchema.Designer.cs +++ b/src/content/Angular-CSharp/Data/SQLServer/00000000000000_CreateIdentitySchema.Designer.cs @@ -86,150 +86,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetUsers"); }); - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("DeviceCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => - { - b.Property("Id") - .HasMaxLength(450) - .HasColumnType("nvarchar(450)"); - - b.Property("Algorithm") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasMaxLength(50000); - - b.Property("DataProtected") - .HasColumnType("bit"); - - b.Property("IsX509Certificate") - .HasColumnType("bit"); - - b.Property("Use") - .HasMaxLength(450) - .HasColumnType("nvarchar(450)"); - - b.Property("Version") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("Use"); - - b.ToTable("Keys"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ConsumedTime") - .HasColumnType("datetime2"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.HasKey("Key"); - - b.HasIndex("ConsumedTime"); - - b.HasIndex("Expiration"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.HasIndex("SubjectId", "SessionId", "Type"); - - b.ToTable("PersistedGrants"); - }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { b.Property("Id") diff --git a/src/content/Angular-CSharp/Data/SQLServer/00000000000000_CreateIdentitySchema.cs b/src/content/Angular-CSharp/Data/SQLServer/00000000000000_CreateIdentitySchema.cs index aa6cbcdd..e4988b3b 100644 --- a/src/content/Angular-CSharp/Data/SQLServer/00000000000000_CreateIdentitySchema.cs +++ b/src/content/Angular-CSharp/Data/SQLServer/00000000000000_CreateIdentitySchema.cs @@ -46,63 +46,6 @@ protected override void Up(MigrationBuilder migrationBuilder) table.PrimaryKey("PK_AspNetUsers", x => x.Id); }); - migrationBuilder.CreateTable( - name: "DeviceCodes", - columns: table => new - { - UserCode = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - DeviceCode = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - SubjectId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - SessionId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Description = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - CreationTime = table.Column(type: "datetime2", nullable: false), - Expiration = table.Column(type: "datetime2", nullable: false), - Data = table.Column(type: "nvarchar(max)", maxLength: 50000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_DeviceCodes", x => x.UserCode); - }); - - migrationBuilder.CreateTable( - name: "Keys", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Version = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - Use = table.Column(type: "nvarchar(450)", maxLength: 450, nullable: true), - Algorithm = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), - IsX509Certificate = table.Column(type: "bit", nullable: false), - DataProtected = table.Column(type: "bit", nullable: false), - Data = table.Column(type: "nvarchar(max)", maxLength: 50000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Keys", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "PersistedGrants", - columns: table => new - { - Key = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), - SubjectId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - SessionId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Description = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - CreationTime = table.Column(type: "datetime2", nullable: false), - Expiration = table.Column(type: "datetime2", nullable: true), - ConsumedTime = table.Column(type: "datetime2", nullable: true), - Data = table.Column(type: "nvarchar(max)", maxLength: 50000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_PersistedGrants", x => x.Key); - }); - migrationBuilder.CreateTable( name: "AspNetRoleClaims", columns: table => new @@ -247,42 +190,6 @@ protected override void Up(MigrationBuilder migrationBuilder) column: "NormalizedUserName", unique: true, filter: "[NormalizedUserName] IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "IX_DeviceCodes_DeviceCode", - table: "DeviceCodes", - column: "DeviceCode", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_DeviceCodes_Expiration", - table: "DeviceCodes", - column: "Expiration"); - - migrationBuilder.CreateIndex( - name: "IX_Keys_Use", - table: "Keys", - column: "Use"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_ConsumedTime", - table: "PersistedGrants", - column: "ConsumedTime"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_Expiration", - table: "PersistedGrants", - column: "Expiration"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_SubjectId_ClientId_Type", - table: "PersistedGrants", - columns: new[] { "SubjectId", "ClientId", "Type" }); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_SubjectId_SessionId_Type", - table: "PersistedGrants", - columns: new[] { "SubjectId", "SessionId", "Type" }); } protected override void Down(MigrationBuilder migrationBuilder) @@ -299,15 +206,6 @@ protected override void Down(MigrationBuilder migrationBuilder) migrationBuilder.DropTable( name: "AspNetUserRoles"); - migrationBuilder.DropTable( - name: "AspNetUserTokens"); - - migrationBuilder.DropTable( - name: "DeviceCodes"); - - migrationBuilder.DropTable( - name: "Keys"); - migrationBuilder.DropTable( name: "PersistedGrants"); diff --git a/src/content/Angular-CSharp/Data/SQLServer/ApplicationDbContextModelSnapshot.cs b/src/content/Angular-CSharp/Data/SQLServer/ApplicationDbContextModelSnapshot.cs index f99a5498..89263d3d 100644 --- a/src/content/Angular-CSharp/Data/SQLServer/ApplicationDbContextModelSnapshot.cs +++ b/src/content/Angular-CSharp/Data/SQLServer/ApplicationDbContextModelSnapshot.cs @@ -84,150 +84,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("AspNetUsers"); }); - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("DeviceCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => - { - b.Property("Id") - .HasMaxLength(450) - .HasColumnType("nvarchar(450)"); - - b.Property("Algorithm") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasMaxLength(50000); - - b.Property("DataProtected") - .HasColumnType("bit"); - - b.Property("IsX509Certificate") - .HasColumnType("bit"); - - b.Property("Use") - .HasMaxLength(450) - .HasColumnType("nvarchar(450)"); - - b.Property("Version") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("Use"); - - b.ToTable("Keys"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ConsumedTime") - .HasColumnType("datetime2"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.HasKey("Key"); - - b.HasIndex("ConsumedTime"); - - b.HasIndex("Expiration"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.HasIndex("SubjectId", "SessionId", "Type"); - - b.ToTable("PersistedGrants"); - }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { b.Property("Id") diff --git a/src/content/Angular-CSharp/Data/SQLite/00000000000000_CreateIdentitySchema.Designer.cs b/src/content/Angular-CSharp/Data/SQLite/00000000000000_CreateIdentitySchema.Designer.cs index 629c3bd0..50e1f578 100644 --- a/src/content/Angular-CSharp/Data/SQLite/00000000000000_CreateIdentitySchema.Designer.cs +++ b/src/content/Angular-CSharp/Data/SQLite/00000000000000_CreateIdentitySchema.Designer.cs @@ -1,4 +1,4 @@ -// +// using System; using Company.WebApplication1.Data; using Microsoft.EntityFrameworkCore; @@ -82,149 +82,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetUsers"); }); - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("CreationTime") - .HasColumnType("TEXT"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("TEXT"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("DeviceCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("Algorithm") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("Created") - .HasColumnType("TEXT"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("TEXT"); - - b.Property("DataProtected") - .HasColumnType("INTEGER"); - - b.Property("IsX509Certificate") - .HasColumnType("INTEGER"); - - b.Property("Use") - .HasMaxLength(450) - .HasColumnType("TEXT"); - - b.Property("Version") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("Use"); - - b.ToTable("Keys"); - }); - - modelBuilder.Entity("Duende.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("ConsumedTime") - .HasColumnType("TEXT"); - - b.Property("CreationTime") - .HasColumnType("TEXT"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("TEXT"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Expiration") - .HasColumnType("TEXT"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.HasKey("Key"); - - b.HasIndex("ConsumedTime"); - - b.HasIndex("Expiration"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.HasIndex("SubjectId", "SessionId", "Type"); - - b.ToTable("PersistedGrants"); - }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { b.Property("Id") diff --git a/src/content/Angular-CSharp/Data/SQLite/00000000000000_CreateIdentitySchema.cs b/src/content/Angular-CSharp/Data/SQLite/00000000000000_CreateIdentitySchema.cs index ee8aac5d..9c07cedd 100644 --- a/src/content/Angular-CSharp/Data/SQLite/00000000000000_CreateIdentitySchema.cs +++ b/src/content/Angular-CSharp/Data/SQLite/00000000000000_CreateIdentitySchema.cs @@ -46,63 +46,6 @@ protected override void Up(MigrationBuilder migrationBuilder) table.PrimaryKey("PK_AspNetUsers", x => x.Id); }); - migrationBuilder.CreateTable( - name: "DeviceCodes", - columns: table => new - { - UserCode = table.Column(type: "TEXT", maxLength: 200, nullable: false), - DeviceCode = table.Column(type: "TEXT", maxLength: 200, nullable: false), - SubjectId = table.Column(type: "TEXT", maxLength: 200, nullable: true), - SessionId = table.Column(type: "TEXT", maxLength: 100, nullable: true), - ClientId = table.Column(type: "TEXT", maxLength: 200, nullable: false), - Description = table.Column(type: "TEXT", maxLength: 200, nullable: true), - CreationTime = table.Column(type: "TEXT", nullable: false), - Expiration = table.Column(type: "TEXT", nullable: false), - Data = table.Column(type: "TEXT", maxLength: 50000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_DeviceCodes", x => x.UserCode); - }); - - migrationBuilder.CreateTable( - name: "Keys", - columns: table => new - { - Id = table.Column(type: "TEXT", nullable: false), - Version = table.Column(type: "INTEGER", nullable: false), - Created = table.Column(type: "TEXT", nullable: false), - Use = table.Column(type: "TEXT", maxLength: 450, nullable: true), - Algorithm = table.Column(type: "TEXT", maxLength: 100, nullable: false), - IsX509Certificate = table.Column(type: "INTEGER", nullable: false), - DataProtected = table.Column(type: "INTEGER", nullable: false), - Data = table.Column(type: "TEXT", maxLength: 50000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Keys", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "PersistedGrants", - columns: table => new - { - Key = table.Column(type: "TEXT", maxLength: 200, nullable: false), - Type = table.Column(type: "TEXT", maxLength: 50, nullable: false), - SubjectId = table.Column(type: "TEXT", maxLength: 200, nullable: true), - SessionId = table.Column(type: "TEXT", maxLength: 100, nullable: true), - ClientId = table.Column(type: "TEXT", maxLength: 200, nullable: false), - Description = table.Column(type: "TEXT", maxLength: 200, nullable: true), - CreationTime = table.Column(type: "TEXT", nullable: false), - Expiration = table.Column(type: "TEXT", nullable: true), - ConsumedTime = table.Column(type: "TEXT", nullable: true), - Data = table.Column(type: "TEXT", maxLength: 50000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_PersistedGrants", x => x.Key); - }); - migrationBuilder.CreateTable( name: "AspNetRoleClaims", columns: table => new @@ -245,42 +188,6 @@ protected override void Up(MigrationBuilder migrationBuilder) table: "AspNetUsers", column: "NormalizedUserName", unique: true); - - migrationBuilder.CreateIndex( - name: "IX_DeviceCodes_DeviceCode", - table: "DeviceCodes", - column: "DeviceCode", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_DeviceCodes_Expiration", - table: "DeviceCodes", - column: "Expiration"); - - migrationBuilder.CreateIndex( - name: "IX_Keys_Use", - table: "Keys", - column: "Use"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_ConsumedTime", - table: "PersistedGrants", - column: "ConsumedTime"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_Expiration", - table: "PersistedGrants", - column: "Expiration"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_SubjectId_ClientId_Type", - table: "PersistedGrants", - columns: new[] { "SubjectId", "ClientId", "Type" }); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_SubjectId_SessionId_Type", - table: "PersistedGrants", - columns: new[] { "SubjectId", "SessionId", "Type" }); } protected override void Down(MigrationBuilder migrationBuilder) @@ -300,15 +207,6 @@ protected override void Down(MigrationBuilder migrationBuilder) migrationBuilder.DropTable( name: "AspNetUserTokens"); - migrationBuilder.DropTable( - name: "DeviceCodes"); - - migrationBuilder.DropTable( - name: "Keys"); - - migrationBuilder.DropTable( - name: "PersistedGrants"); - migrationBuilder.DropTable( name: "AspNetRoles"); diff --git a/src/content/Angular-CSharp/Data/SQLite/ApplicationDbContextModelSnapshot.cs b/src/content/Angular-CSharp/Data/SQLite/ApplicationDbContextModelSnapshot.cs index 1e8a43cf..742a58b3 100644 --- a/src/content/Angular-CSharp/Data/SQLite/ApplicationDbContextModelSnapshot.cs +++ b/src/content/Angular-CSharp/Data/SQLite/ApplicationDbContextModelSnapshot.cs @@ -80,149 +80,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("AspNetUsers"); }); - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("CreationTime") - .HasColumnType("TEXT"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("TEXT"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("DeviceCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("Algorithm") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("Created") - .HasColumnType("TEXT"); - - b.Property("Data") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(50000); - - b.Property("DataProtected") - .HasColumnType("INTEGER"); - - b.Property("IsX509Certificate") - .HasColumnType("INTEGER"); - - b.Property("Use") - .HasMaxLength(450) - .HasColumnType("TEXT"); - - b.Property("Version") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("Use"); - - b.ToTable("Keys"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("ConsumedTime") - .HasColumnType("TEXT"); - - b.Property("CreationTime") - .HasColumnType("TEXT"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("TEXT"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Expiration") - .HasColumnType("TEXT"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.HasKey("Key"); - - b.HasIndex("ConsumedTime"); - - b.HasIndex("Expiration"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.HasIndex("SubjectId", "SessionId", "Type"); - - b.ToTable("PersistedGrants"); - }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { b.Property("Id") diff --git a/src/content/Angular-CSharp/Pages/Shared/_LoginPartial.cshtml b/src/content/Angular-CSharp/Pages/Shared/_LoginPartial.cshtml index 306bec97..293c674f 100644 --- a/src/content/Angular-CSharp/Pages/Shared/_LoginPartial.cshtml +++ b/src/content/Angular-CSharp/Pages/Shared/_LoginPartial.cshtml @@ -3,34 +3,25 @@ @inject SignInManager SignInManager @inject UserManager UserManager -@{ - string? returnUrl = null; - var query = ViewContext.HttpContext.Request.Query; - if (query.ContainsKey("returnUrl")) - { - returnUrl = query["returnUrl"]; - } -} - diff --git a/src/content/Angular-CSharp/Program.cs b/src/content/Angular-CSharp/Program.cs index 0cd7ef97..611105c8 100644 --- a/src/content/Angular-CSharp/Program.cs +++ b/src/content/Angular-CSharp/Program.cs @@ -1,7 +1,4 @@ #if (IndividualLocalAuth) -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Identity.UI; using Microsoft.EntityFrameworkCore; using Company.WebApplication1.Data; using Company.WebApplication1.Models; @@ -22,12 +19,6 @@ builder.Services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores(); - -builder.Services.AddIdentityServer() - .AddApiAuthorization(); - -builder.Services.AddAuthentication() - .AddIdentityServerJwt(); #endif builder.Services.AddControllersWithViews(); @@ -59,15 +50,6 @@ #endif app.UseStaticFiles(); -app.UseRouting(); - -#if (IndividualLocalAuth) -app.UseAuthentication(); -app.UseIdentityServer(); -#endif -#if (!NoAuth) -app.UseAuthorization(); -#endif app.MapControllerRoute( name: "default",