Recently, I implemented a sign-in authentication feature for my Angular application and decided to test it out. The sign-up process worked perfectly fine. However, upon signing out and attempting to sign back in, the header failed to update as expected. Instead, I encountered an error in the console:
Uncaught DOMException: Blocked a frame with origin "chrome-extension://hdokiejnpimakedhajhdlcegeplioahd" from accessing a cross-origin frame. at e [as constructor] (chrome-extension://hdokiejnpimakedhajhdlcegeplioahd/lpfulllib.js:1:1441712) at new e (chrome-extension://hdokiejnpimakedhajhdlcegeplioahd/lpfulllib.js:1:1444920) at chrome-extension://hdokiejnpimakedhajhdlcegeplioahd/lpfulllib.js:1:1461728
Despite the GET request being successful, the response indicated that I was not authenticated:
{authenticated: false, username: null}
authenticated: false
username: null
This was confusing because the request was supposed to be a POST, not a GET. Why did it interpret it as a GET request?
My signin()
method within the authentication service clearly specifies that it should be a POST request:
signin(credentials: SigninCredentials) {
return this.http.post(this.rootUrl + "/auth/signin", credentials).pipe(
tap(() => {
this.signedin$.next(true);
})
);
}
Below is the code for my auth HTTP interceptor:
import { Injectable } from "@angular/core";
import {
HttpEvent,
HttpInterceptor,
HttpHandler,
HttpRequest,
HttpEventType,
} from "@angular/common/http";
import { Observable } from "rxjs";
@Injectable()
export class AuthHttpInterceptor implements HttpInterceptor {
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
// Modify or log the outgoing request
const modifiedReq = req.clone({
withCredentials: true,
});
return next.handle(modifiedReq);
}
}
I don't believe the issue lies within my AuthHttpInterceptor
; rather, I suspect there might be a problem in the AuthService
:
import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { BehaviorSubject } from "rxjs";
import { tap } from "rxjs/operators";
interface UsernameAvailableResponse {
available: boolean;
}
interface SignupCredentials {
username: string;
password: string;
passwordConfirmation: string;
}
interface SignupResponse {
username: string;
}
interface SignedinResponse {
authenticated: boolean;
username: string;
}
interface SigninCredentials {
username: string;
password: string;
}
@Injectable({
providedIn: "root",
})
export class AuthService {
rootUrl = "https://api.my-email.com";
signedin$ = new BehaviorSubject(false);
constructor(private http: HttpClient) {}
usernameAvailable(username: string) {
return this.http.post<UsernameAvailableResponse>(
this.rootUrl + "/auth/username",
{
username,
}
);
}
signup(credentials: SignupCredentials) {
return this.http
.post<SignupResponse>(this.rootUrl + "/auth/signup", credentials)
.pipe(
tap(() => {
this.signedin$.next(true);
})
);
}
checkAuth() {
return this.http
.get<SignedinResponse>(this.rootUrl + "/auth/signedin")
.pipe(
tap(({ authenticated }) => {
this.signedin$.next(authenticated);
})
);
}
signout() {
return this.http.post(this.rootUrl + "/auth/signout", {}).pipe(
tap(() => {
this.signedin$.next(false);
})
);
}
signin(credentials: SigninCredentials) {
return this.http.post(this.rootUrl + "/auth/signin", credentials).pipe(
tap(() => {
this.signedin$.next(true);
})
);
}
}