From cc648afb5333c2652e9c6e939aab0c5e3add1a52 Mon Sep 17 00:00:00 2001 From: Karissa Jacobsen Date: Fri, 6 Jun 2025 12:09:34 -0700 Subject: [PATCH 1/4] restrict allows returnUrls --- .../src/app/core/errorhandler.inteceptor.ts | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/DocuSign.MyAPI/ClientApp/src/app/core/errorhandler.inteceptor.ts b/DocuSign.MyAPI/ClientApp/src/app/core/errorhandler.inteceptor.ts index d3878ae..f849aba 100644 --- a/DocuSign.MyAPI/ClientApp/src/app/core/errorhandler.inteceptor.ts +++ b/DocuSign.MyAPI/ClientApp/src/app/core/errorhandler.inteceptor.ts @@ -40,10 +40,20 @@ export class ErrorHanlderInterceptor implements HttpInterceptor { } else if (error.status === 401) { this.translateService.get('ERRORS.401').subscribe((res: string) => { let snackBarRef = this.notificationService.showInfo(res); - snackBarRef.afterDismissed().subscribe(() => { - window.location.href = - '/account/login?returnUrl=' + this.router.url; + const allowedHosts = ['myapicalls.sampleapps.docusign.com', 'myapicalls-t.sampleapps.docusign.com']; // Add allowed hostnames here + let returnUrl = this.router.url; + + try { + const url = new URL(returnUrl, window.location.origin); + if (!allowedHosts.includes(url.hostname)) { + returnUrl = '/'; // fallback to home if not allowed + } + } catch { + returnUrl = '/'; + } + + window.location.href = `/account/login?returnUrl=${encodeURIComponent(returnUrl)}`; }); }); } From 60fc1f43b52eeba623f3b7b621c431a2b9e7b59a Mon Sep 17 00:00:00 2001 From: Karissa Jacobsen Date: Fri, 6 Jun 2025 12:28:59 -0700 Subject: [PATCH 2/4] debug statement --- .../ClientApp/src/app/core/errorhandler.inteceptor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DocuSign.MyAPI/ClientApp/src/app/core/errorhandler.inteceptor.ts b/DocuSign.MyAPI/ClientApp/src/app/core/errorhandler.inteceptor.ts index f849aba..c060c41 100644 --- a/DocuSign.MyAPI/ClientApp/src/app/core/errorhandler.inteceptor.ts +++ b/DocuSign.MyAPI/ClientApp/src/app/core/errorhandler.inteceptor.ts @@ -43,7 +43,7 @@ export class ErrorHanlderInterceptor implements HttpInterceptor { snackBarRef.afterDismissed().subscribe(() => { const allowedHosts = ['myapicalls.sampleapps.docusign.com', 'myapicalls-t.sampleapps.docusign.com']; // Add allowed hostnames here let returnUrl = this.router.url; - + console.log('returnUrl:', returnUrl); // This will show in the browser console try { const url = new URL(returnUrl, window.location.origin); if (!allowedHosts.includes(url.hostname)) { From bf317018320f9faed4dd4521830f3db485ab82ef Mon Sep 17 00:00:00 2001 From: Karissa Jacobsen Date: Fri, 6 Jun 2025 12:43:57 -0700 Subject: [PATCH 3/4] updates --- .../src/app/core/errorhandler.inteceptor.ts | 15 +++++---------- .../ClientApp/src/app/header/header.component.ts | 16 +++++++++++----- DocuSign.MyAPI/Controllers/AccountController.cs | 5 +++++ 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/DocuSign.MyAPI/ClientApp/src/app/core/errorhandler.inteceptor.ts b/DocuSign.MyAPI/ClientApp/src/app/core/errorhandler.inteceptor.ts index c060c41..5d90665 100644 --- a/DocuSign.MyAPI/ClientApp/src/app/core/errorhandler.inteceptor.ts +++ b/DocuSign.MyAPI/ClientApp/src/app/core/errorhandler.inteceptor.ts @@ -40,20 +40,15 @@ export class ErrorHanlderInterceptor implements HttpInterceptor { } else if (error.status === 401) { this.translateService.get('ERRORS.401').subscribe((res: string) => { let snackBarRef = this.notificationService.showInfo(res); + snackBarRef.afterDismissed().subscribe(() => { - const allowedHosts = ['myapicalls.sampleapps.docusign.com', 'myapicalls-t.sampleapps.docusign.com']; // Add allowed hostnames here let returnUrl = this.router.url; - console.log('returnUrl:', returnUrl); // This will show in the browser console - try { - const url = new URL(returnUrl, window.location.origin); - if (!allowedHosts.includes(url.hostname)) { - returnUrl = '/'; // fallback to home if not allowed - } - } catch { + // Only allow relative paths + if (!returnUrl.startsWith('/')) { returnUrl = '/'; } - - window.location.href = `/account/login?returnUrl=${encodeURIComponent(returnUrl)}`; + window.location.href = + '/account/login?returnUrl=' + returnUrl; }); }); } diff --git a/DocuSign.MyAPI/ClientApp/src/app/header/header.component.ts b/DocuSign.MyAPI/ClientApp/src/app/header/header.component.ts index 597eceb..f592cac 100644 --- a/DocuSign.MyAPI/ClientApp/src/app/header/header.component.ts +++ b/DocuSign.MyAPI/ClientApp/src/app/header/header.component.ts @@ -17,12 +17,18 @@ export class AppHeaderComponent implements OnInit { ) {} ngOnInit(): void { - this.router.events.subscribe((event) => { - if (event instanceof NavigationEnd) { - this.url = this.router.url; + this.router.events.subscribe((event) => { + if (event instanceof NavigationEnd) { + let currentUrl = this.router.url; + // Only allow relative paths + if (currentUrl.startsWith('/')) { + this.url = currentUrl; + } else { + this.url = '/'; } - }); - } + } + }); +} get isLoggedIn(): Observable { return this.accountService.isLoggedIn(); } diff --git a/DocuSign.MyAPI/Controllers/AccountController.cs b/DocuSign.MyAPI/Controllers/AccountController.cs index 3ba4a35..ea5f709 100644 --- a/DocuSign.MyAPI/Controllers/AccountController.cs +++ b/DocuSign.MyAPI/Controllers/AccountController.cs @@ -27,6 +27,11 @@ public async Task> GetAccountId() [Route("login")] public IActionResult Login(string returnUrl = "/") { + if (string.IsNullOrEmpty(returnUrl) || !Url.IsLocalUrl(returnUrl)) + { + returnUrl = "/"; + } + return Challenge(new AuthenticationProperties() { RedirectUri = returnUrl, AllowRefresh = true }); } From 0b51f4287d1867922aaa5a4e38798bb9ca05c817 Mon Sep 17 00:00:00 2001 From: Karissa Jacobsen Date: Fri, 6 Jun 2025 12:49:52 -0700 Subject: [PATCH 4/4] spacing issue --- .../src/app/header/header.component.ts | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/DocuSign.MyAPI/ClientApp/src/app/header/header.component.ts b/DocuSign.MyAPI/ClientApp/src/app/header/header.component.ts index f592cac..4a9b6fc 100644 --- a/DocuSign.MyAPI/ClientApp/src/app/header/header.component.ts +++ b/DocuSign.MyAPI/ClientApp/src/app/header/header.component.ts @@ -17,18 +17,18 @@ export class AppHeaderComponent implements OnInit { ) {} ngOnInit(): void { - this.router.events.subscribe((event) => { - if (event instanceof NavigationEnd) { - let currentUrl = this.router.url; - // Only allow relative paths - if (currentUrl.startsWith('/')) { - this.url = currentUrl; - } else { - this.url = '/'; + this.router.events.subscribe((event) => { + if (event instanceof NavigationEnd) { + let currentUrl = this.router.url; + // Only allow relative paths + if (currentUrl.startsWith('/')) { + this.url = currentUrl; + } else { + this.url = '/'; + } } - } - }); -} + }); + } get isLoggedIn(): Observable { return this.accountService.isLoggedIn(); }