{"id":72457,"date":"2022-07-18T08:41:53","date_gmt":"2022-07-18T06:41:53","guid":{"rendered":"https:\/\/drafts.code-maze.com\/?p=72457"},"modified":"2022-07-18T08:41:53","modified_gmt":"2022-07-18T06:41:53","slug":"cookie-authentication-aspnetcore-angular","status":"publish","type":"post","link":"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/","title":{"rendered":"Cookie Authentication With ASP.NET Core and Angular"},"content":{"rendered":"<p>In this article, we&#8217;re going to learn about cookie authentication with ASP.NET Core and Angular.<\/p>\n<p>We&#8217;ll create an ASP.NET Core Web API with sign-in, sign-out, and a protected user endpoint for demonstration. In Angular, we&#8217;ll access the protected user endpoint after successful authentication based on cookies.<\/p>\n<div style=\"padding: 20px; border-left: 5px #dc2323 solid; display: block; margin-bottom: 20px; box-shadow: 1px 1px 5px 0px lightgrey;\">To download the source code for this article, you can visit our <a href=\"https:\/\/github.com\/CodeMazeBlog\/CodeMazeGuides\/tree\/main\/authorization-dotnet\/CookieAuthenticationWithAngular\" target=\"_blank\" rel=\"nofollow noopener\">GitHub repository<\/a>.<\/div>\n<p>Let&#8217;s begin.<\/p>\n<h2>What Are HTTP Cookies<\/h2>\n<p>A server transmits a <strong>small piece of data<\/strong> called an HTTP cookie (also known as a web cookie or browser cookie) to a user&#8217;s web browser. With subsequent requests, the browser may save the cookie and <strong>transmit it back<\/strong> to the same server.<\/p>\n<p>Cookies help to identify if the request comes from the same browser. Hence, we use cookies for authentication purposes.<\/p>\n<p>To learn more about cookies, please refer to this <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Cookies\" target=\"_blank\" rel=\"nofollow noopener\">article<\/a>.<\/p>\n<h2>How to Setup Cookie Authentication in ASP.NET Core<\/h2>\n<p>In one of our <a href=\"https:\/\/code-maze.com\/dotnet-multiple-authentication-schemes\/\" target=\"_blank\" rel=\"noopener\">previous articles<\/a>, we learned about using multiple authentication schemes in ASP.NET Core. In this article, we&#8217;ll focus mainly on cookie authentication.<\/p>\n<p>First, let&#8217;s create a new project using <strong>ASP.NET Core with Angular<\/strong> project template in Visual Studio.<\/p>\n<p>After that, we need to change the <code>Program.cs<\/code> to enable cookie authentication:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)\r\n    .AddCookie(options =&gt;\r\n    {\r\n        options.Events.OnRedirectToLogin = (context) =&gt;\r\n        {\r\n            context.Response.StatusCode = 401;\r\n            return Task.CompletedTask;\r\n        };\r\n    });<\/pre>\n<p>Here, the <code>AddAuthentication<\/code> method adds a default authentication scheme using an inbuilt <code>CookieAuthenticationDefaults.AuthenticationScheme<\/code> constant. After that, the <code>AddCookie<\/code> method adds the required services for cookie authentication.<\/p>\n<p>By default, cookie authentication redirects the user to the login URL if authentication failed. Hence, we&#8217;re setting the delegate function <code>options.Events.OnRedirectToLogin<\/code> with a lambda expression. This expression returns an <strong>unauthorized<\/strong> HTTP status code <code>401<\/code>.<\/p>\n<p>After this is done, we need to enable the authentication in <code>Program.cs<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">app.UseAuthentication();\r\napp.UseAuthorization();\r\n\r\napp.MapDefaultControllerRoute();<\/pre>\n<p>Make sure to add the methods in the same order. The <code>UseAuthentication<\/code> and <code>UseAuthorization<\/code> methods add the required <a href=\"https:\/\/code-maze.com\/working-with-asp-net-core-middleware\/\" target=\"_blank\" rel=\"noopener\">middleware<\/a> to the pipeline to authenticate the user on each request. These middlewares will also set the <code>User<\/code> property in the controller.<\/p>\n<p>Now we can start creating the endpoints. Let&#8217;s create a new controller named <code>AuthController<\/code> with <a href=\"https:\/\/code-maze.com\/apicontroller-attribute-in-asp-net-core-web-api\/\" target=\"_blank\" rel=\"noopener\">ApiController<\/a> and <strong>Route<\/strong> attributes:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">[ApiController]\r\n[Route(\"\/api\/auth\")]\r\npublic class AuthController : Controller\r\n{\r\n}<\/pre>\n<p>Here, the <code>ApiController<\/code> attribute enables the API-specific behavior. With <code>Route<\/code> attribute, we specify the root API path <code>\/api\/auth<\/code> for all the action methods in this controller.<\/p>\n<p>Let&#8217;s create the required models for our endpoints using a\u00a0<a href=\"https:\/\/code-maze.com\/csharp-records\/\" target=\"_blank\" rel=\"noopener\">record<\/a> type:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public record SignInRequest(string Email, string Password);\r\npublic record Response(bool IsSuccess, string Message);\r\npublic record UserClaim(string Type, string Value);\r\npublic record User(string Email, string Name, string Password);<\/pre>\n<h3>Sign In Endpoint<\/h3>\n<p>For <strong>demonstration purposes<\/strong>, we&#8217;re creating a simple user store using a private field in <code>AuthController<\/code>. It will hold the hardcoded user information:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">private List&lt;User&gt; users = new()\r\n{\r\n    new(\"user1@test.com\", \"User 1\", \"user1\"),\r\n    new(\"user2@test.com\", \"User 2\", \"user2\"),\r\n};<\/pre>\n<p>Now, let&#8217;s create the endpoint <code>api\/auth\/signin<\/code> as HTTP post method:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">[HttpPost(\"signin\")]\r\npublic async Task&lt;IActionResult&gt; SignInAsync([FromBody] SignInRequest signInRequest)\r\n{\r\n    var user = users.FirstOrDefault(x =&gt; x.Email == signInRequest.Email &amp;&amp;\r\n                                        x.Password == signInRequest.Password);\r\n    if (user is null)\r\n    {\r\n        return BadRequest(new Response(false, \"Invalid credentials.\"));\r\n    }\r\n\r\n    var claims = new List&lt;Claim&gt;\r\n    {\r\n        new Claim(type: ClaimTypes.Email, value: signInRequest.Email),\r\n        new Claim(type: ClaimTypes.Name,value: user.Name)\r\n    };\r\n    var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);\r\n\r\n    await HttpContext.SignInAsync(\r\n        CookieAuthenticationDefaults.AuthenticationScheme,\r\n        new ClaimsPrincipal(identity),\r\n        new AuthenticationProperties\r\n        {\r\n            IsPersistent = true,\r\n            AllowRefresh = true,\r\n            ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(10),\r\n        });\r\n\r\n    return Ok(new Response(true, \"Signed in successfully\"));\r\n}<\/pre>\n<p>Here, with the <code>signInRequest<\/code> parameter, we receive the <code>Email<\/code> and <code>Password<\/code> values. Using these values, we&#8217;re checking our local user store <code>users<\/code> whether the given user exists or not.<\/p>\n<p>If the user credentials are valid, we create <code>claims<\/code> and then the HTTP cookie using the <code>HttpContext.SignInAsync<\/code> method.<\/p>\n<h3>User Endpoint<\/h3>\n<p>Signed-in users can access the protected endpoints. Let&#8217;s create one protected GET endpoint <code>\/api\/auth\/user<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">[Authorize]\r\n[HttpGet(\"user\")]\r\npublic IActionResult GetUser()\r\n{\r\n    var userClaims = User.Claims.Select(x =&gt; new UserClaim(x.Type, x.Value)).ToList();\r\n\r\n    return Ok(userClaims);\r\n}<\/pre>\n<p>In this endpoint, we&#8217;re returning the currently signed-in user&#8217;s claims. The <code>Authorize<\/code> attribute protects this endpoint. Since we&#8217;re using cookie authentication, it checks the cookie in the request&#8217;s header and populates the <code>User<\/code> object. If the cookie is invalid, it returns <code>401<\/code> HTTP status code automatically.<\/p>\n<h3>Sign Out Endpoint<\/h3>\n<p>Finally, let&#8217;s create a sign-out endpoint <code>\/api\/auth\/signout<\/code> to clear the cookies:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">[Authorize]\r\n[HttpGet(\"signout\")]\r\npublic async Task SignOutAsync()\r\n{\r\n    await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);\r\n}<\/pre>\n<p>Here, the endpoint will clear the cookies from the user&#8217;s browser by issuing a new expired cookie without any claims data.<\/p>\n<h2>How to Authenticate Cookies in Angular<\/h2>\n<p>In this section, we will work with the <a href=\"https:\/\/code-maze.com\/angular-series\/\" target=\"_blank\" rel=\"noopener\">Angular part<\/a> of our application.<\/p>\n<h3>Auth Service<\/h3>\n<p>First, let&#8217;s create the necessary interfaces for the API responses:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"typescript\">export interface UserClaim {\r\n    type: string;\r\n    value: string;\r\n}\r\n\r\nexport interface Response {\r\n    isSuccess: boolean;\r\n    message: string;\r\n}<\/pre>\n<p>Now we can create the <code>AuthService<\/code> class to do all the necessary API calls:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"typescript\">@Injectable({\r\n    providedIn: 'root',\r\n})\r\nexport class AuthService {\r\n    constructor(private http: HttpClient) {}\r\n\r\n    public signIn(email: string, password: string) {\r\n        return this.http.post&lt;Response&gt;('api\/auth\/signin', {\r\n            email: email,\r\n            password: password\r\n        });\r\n    }\r\n\r\n    public signOut() {\r\n        return this.http.get('api\/auth\/signout');\r\n    }\r\n\r\n    public user() {\r\n        return this.http.get&lt;UserClaim[]&gt;('api\/auth\/user');\r\n    }\r\n\r\n    public isSignedIn(): Observable&lt;boolean&gt; {\r\n        return this.user().pipe(\r\n            map((userClaims) =&gt; {\r\n                const hasClaims = userClaims.length &gt; 0;\r\n                return !hasClaims ? false : true;\r\n            }),\r\n            catchError((error) =&gt; {\r\n                return of(false);\r\n            }));\r\n    }\r\n}\r\n<\/pre>\n<p>In <code>AuthService<\/code>, we create <code>signIn<\/code>, <code>user<\/code>, and <code>signOut<\/code> functions. These functions call the respective API endpoints in the backend.<\/p>\n<p>Apart from these functions, we create another <code>isSignedIn<\/code> function. This function calls the user endpoint and returns <code>true<\/code> or <code>false<\/code> based on its authentication status.<\/p>\n<h3>Sign In Component<\/h3>\n<p>Now, let&#8217;s create a sign-in component HTML to input user credentials:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\">&lt;div class=\"d-flex flex-column align-items-center justify-content-center\" *ngIf=\"!signedIn else signedInAlready\"&gt;\r\n    &lt;div&gt;Please Sign In to continue&lt;\/div&gt;\r\n    &lt;form class=\"form w-50\" [formGroup]=\"loginForm\" (submit)=\"signin($event)\"&gt;\r\n        &lt;div class=\"row m-3\"&gt;\r\n            &lt;label for=\"name\"&gt;Email*&lt;\/label&gt;\r\n            &lt;input class=\"col form-field\" name=\"email\" formControlName=\"email\" \/&gt;\r\n        &lt;\/div&gt;\r\n        &lt;div class=\"row m-3\"&gt;\r\n            &lt;label for=\"password\"&gt;Password*&lt;\/label&gt;\r\n            &lt;input class=\"col form-field\" type=\"password\" name=\"password\" formControlName=\"password\" autocomplete=\"on\" \/&gt;\r\n        &lt;\/div&gt;\r\n        &lt;div class=\"row m-3\" *ngIf=\"authFailed\"&gt;\r\n            &lt;label style=\"color: red\"&gt;Invalid credentials&lt;\/label&gt;\r\n        &lt;\/div&gt;\r\n        &lt;div class=\"row m-3\"&gt;\r\n            &lt;button class=\"col btn btn-primary\" [disabled]=\"!loginForm.valid\" type=\"submit\"&gt;Sign In&lt;\/button&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/form&gt;\r\n    &lt;div class=\"alert-info p-2\"&gt;\r\n        Try user1@test.com \/ user1\r\n        or user2@test.com \/ user2\r\n    &lt;\/div&gt;\r\n&lt;\/div&gt;\r\n\r\n&lt;ng-template #signedInAlready&gt;\r\n    &lt;h4&gt;Sign In&lt;\/h4&gt;\r\n    &lt;div&gt;\r\n        You are already signed in!\r\n    &lt;\/div&gt;\r\n&lt;\/ng-template&gt;<\/pre>\n<p>After that, let&#8217;s create the <code>SignInComponent<\/code> class:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"typescript\">@Component({\r\n    selector: 'app-signin-component',\r\n    templateUrl: '.\/signin.component.html'\r\n})\r\nexport class SignInComponent implements OnInit {\r\n    loginForm!: FormGroup;\r\n    authFailed: boolean = false;\r\n    signedIn: boolean = false;\r\n\r\n    constructor(private authService: AuthService,\r\n        private formBuilder: FormBuilder,\r\n        private router: Router) {\r\n        this.authService.isSignedIn().subscribe(\r\n            isSignedIn =&gt; {\r\n                this.signedIn = isSignedIn;\r\n            });\r\n    }\r\n\r\n    ngOnInit(): void {\r\n        this.authFailed = false;\r\n        this.loginForm = this.formBuilder.group(\r\n            {\r\n                email: ['', [Validators.required, Validators.email]],\r\n                password: ['', [Validators.required]]\r\n            });\r\n    }\r\n\r\n    public signIn(event: any) {\r\n        if (!this.loginForm.valid) {\r\n            return;\r\n        }\r\n        const userName = this.loginForm.get('email')?.value;\r\n        const password = this.loginForm.get('password')?.value;\r\n        this.authService.signIn(userName, password).subscribe(\r\n            response =&gt; {\r\n                if (response.isSuccess) {\r\n                    this.router.navigateByUrl('user')\r\n                }\r\n            },\r\n            error =&gt; {\r\n                if (!error?.error?.isSuccess) {\r\n                    this.authFailed = true;\r\n                }\r\n            });\r\n    }\r\n}\r\n<\/pre>\n<p>In this component, we are checking whether the user is signed in or not in the <code>constructor<\/code>. In <code>ngOnInit<\/code> function, we&#8217;re initializing the <code>loginForm<\/code> with two form fields <code>email<\/code> and <code>password<\/code>.\u00a0<\/p>\n<p>Whenever the form is submitted, the <code>signIn<\/code> function gets called. In this function, we retrieve the form values and then pass them to the <code>this.authService.signIn<\/code> function. This function calls the <code>\/api\/auth\/signin<\/code> endpoint and returns the result.<\/p>\n<p>If the credentials are valid, the API sets the cookie in the <strong>response header<\/strong> with the key <code>set-cookie<\/code>:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\">set-cookie: .AspNetCore.Cookies=CfDJ8KZELxg4LUBBvlmGEWUFluV ... _w8capcAdZ3fvcL18VNo5fReX1juZAI; expires=Sun, 10 Jul 2022 06:34:18 GMT; path=\/; secure; samesite=lax; httponly<\/code><\/p>\n<p>If we look at the cookie, the user claims are encrypted. The browser stores it and pass this cookie in the subsequent <strong>request header<\/strong> with the key <code>Cookie<\/code>:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\">Cookie: .AspNetCore.Cookies=CfDJ8KZELxg4LUBBvlmGEWUFluVgrOiEyLK6GfUQIr8qlbJKQBcCANpte0iuC9uBZ-_zfJl-W...<\/code><\/p>\n<h3>User Component<\/h3>\n<p>Once the sign-in is successful, we redirect the user to another component called <code>UserComponent<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"typescript\">@Component({\r\n    selector: 'app-user',\r\n    templateUrl: '.\/user.component.html',\r\n})\r\nexport class UserComponent {\r\n    userClaims: UserClaim[] = [];\r\n    constructor(private authService: AuthService) {\r\n        this.getUser();\r\n    }\r\n\r\n    getUser() {\r\n        this.authService.user().subscribe(\r\n            result =&gt; {\r\n                this.userClaims = result;\r\n            });\r\n    }\r\n}<\/pre>\n<p>In this component, we call the <code>\/api\/auth\/user<\/code> endpoint using the <code>getUser()<\/code> function.<\/p>\n<p>If the cookie is valid, the protected user endpoint will return the <strong>200 (Ok)<\/strong> response. Otherwise, the endpoint will return <strong>401 (Unauthorized)<\/strong>.<\/p>\n<h3>Sign Out Component<\/h3>\n<p>Now, let&#8217;s implement the <code>SignOutComponent<\/code>. It is as simple as calling the <code>this.authService.signOut()<\/code> function on click of a &#8216;Sign Out&#8217; button:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"typescript\">@Component({\r\n    selector: 'app-signout-component',\r\n    templateUrl: '.\/signout.component.html'\r\n})\r\nexport class SignOutComponent {\r\n    constructor(private authService: AuthService) {\r\n        this.signout();\r\n    }\r\n\r\n    public signout() {\r\n        this.authService.signOut().subscribe();\r\n    }\r\n}<\/pre>\n<p>As soon as the <code>\/api\/auth\/signout<\/code> endpoint is called a cookie will be invalidated. The server does this by issuing expired cookies in the same <code>set-cookie<\/code> response header:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\">set-cookie: .AspNetCore.Cookies=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=\/; secure; samesite=lax; httponly<\/code><\/p>\n<p>So, calling any protected endpoint subsequently will return 401.<\/p>\n<h3>Auth Interceptor<\/h3>\n<p>So far, we didn&#8217;t handle the unauthorized response. Under any circumstance, if the user tries to access the protected endpoints, we should redirect them to the Sign In page.\u00a0To achieve this, we can implement our custom <a href=\"https:\/\/angular.io\/api\/common\/http\/HttpInterceptor\" target=\"_blank\" rel=\"nofollow noopener\">HttpInterceptor<\/a>.<\/p>\n<p>Let&#8217;s create a <code>AuthInterceptor<\/code> class to intercept the request:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"typescript\">@Injectable()\r\nexport class AuthInterceptor implements HttpInterceptor {\r\n    constructor(private router: Router) { }\r\n    intercept(req: HttpRequest&lt;any&gt;, next: HttpHandler): Observable&lt;HttpEvent&lt;any&gt;&gt; {\r\n        return next.handle(req).pipe(tap(() =&gt; { },\r\n            (err: any) =&gt; {\r\n                if (err instanceof HttpErrorResponse) {\r\n                    if (err.status !== 401) {\r\n                        return;\r\n                    }\r\n                    this.router.navigate(['signin']);\r\n                }\r\n            }));\r\n    }\r\n}<\/pre>\n<p>Here, we&#8217;re intercepting the response of all the API calls using the <code>pipe<\/code> and <code>tap<\/code> <a href=\"https:\/\/angular.io\/guide\/rx-library\" target=\"_blank\" rel=\"noopener nofollow\">RxJS<\/a> operators. If any of the endpoints return <strong>401<\/strong>, then we redirect the user to the sign-in page.<\/p>\n<h3>Auth Guard<\/h3>\n<p>The above solution works only if the page makes any request to the protected API endpoint.<\/p>\n<p>To overcome this and to protect any angular route, we can implement a <a href=\"https:\/\/angular.io\/api\/router\/CanActivate\" target=\"_blank\" rel=\"noopener nofollow\">guard<\/a> class:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"typescript\">@Injectable()\r\nexport class AuthGuard implements CanActivate {\r\n    constructor(private authService: AuthService, private router: Router) { }\r\n\r\n    canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) {\r\n        return this.isSignedIn();\r\n    }\r\n\r\n    isSignedIn(): Observable&lt;boolean&gt; {\r\n        return this.authService.isSignedIn().pipe(\r\n            map((isSignedIn) =&gt; {\r\n                if (!isSignedIn) {\r\n                    this.router.navigate(['signin']);\r\n                    return false;\r\n                }\r\n                return true;\r\n            }));\r\n    }\r\n}<\/pre>\n<p>Here, the <code>canActivate<\/code> function checks for the sign-in status of the user. If signed in, we allow the user to access the page. Otherwise, redirect them to the sign-in page.<\/p>\n<p>Routes can use our <code>AuthGuard<\/code> in its declaration using <code>canActivate<\/code> key:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"typescript\">RouterModule.forRoot([\r\n    {\r\n        path: 'secured',\r\n        component: SecuredComponent,\r\n        pathMatch: 'full',\r\n        canActivate: [AuthGuard]\r\n    }\r\n])<\/pre>\n<h3>Provider Registration<\/h3>\n<p>We need to register both <code>AuthInterceptor<\/code> and <code>AuthGuard<\/code> in the <code>AppModule<\/code>\u00a0<a href=\"https:\/\/angular.io\/guide\/providers\" target=\"_blank\" rel=\"nofollow noopener\">providers<\/a> in order to take effect:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"typescript\">providers: [\r\n    {\r\n        provide: HTTP_INTERCEPTORS,\r\n        useFactory: function (router: Router) {\r\n            return new AuthInterceptor(router);\r\n        },\r\n        multi: true,\r\n        deps: [Router]\r\n    },\r\n    AuthGuard\r\n],<\/pre>\n<h3>Testing the application<\/h3>\n<p>Finally, let&#8217;s run the application through Visual Studio or <code>dotnet run<\/code> command. In the browser, we see the &#8216;Sign In&#8217; page to input the credentials.<\/p>\n<p>When we try to use invalid credentials, we cannot sign in. For valid credentials, the server issues cookies to the browser and we redirect to the User page. On this page, we see the authenticated user&#8217;s claims:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"json\">[\r\n  {\r\n    \"type\": \"http:\/\/schemas.xmlsoap.org\/ws\/2005\/05\/identity\/claims\/emailaddress\",\r\n    \"value\": \"user1@test.com\"\r\n  },\r\n  {\r\n    \"type\": \"http:\/\/schemas.xmlsoap.org\/ws\/2005\/05\/identity\/claims\/name\",\r\n    \"value\": \"User 1\"\r\n  }\r\n]<\/pre>\n<p>Eventually, we can access the &#8216;Secured&#8217; page as well. Once we click on the &#8216;Sign Out&#8217; button, the server invalidates the cookie. Hence, we cannot access both the &#8216;User&#8217; and &#8216;Secured&#8217; pages after we sign out. At this point, the browser always redirects us to the &#8216;Sign In&#8217; page to input valid credentials.<\/p>\n<h2>Conclusion<\/h2>\n<p>In this article, we&#8217;ve learned to use cookie authentication with ASP.NET Core and Angular in detail with a code sample. Initially, we looked at creating the endpoints. After that, we created the angular components, interceptors, and guards to properly authenticate the user.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this article, we&#8217;re going to learn about cookie authentication with ASP.NET Core and Angular. We&#8217;ll create an ASP.NET Core Web API with sign-in, sign-out, and a protected user endpoint for demonstration. In Angular, we&#8217;ll access the protected user endpoint after successful authentication based on cookies. Let&#8217;s begin. What Are HTTP Cookies A server transmits [&hellip;]<\/p>\n","protected":false},"author":6,"featured_media":62187,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","footnotes":""},"categories":[168,171],"tags":[23,586,1310,1356],"class_list":["post-72457","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-angular","category-http","tag-angular","tag-asp-net-core-web-api","tag-cookie","tag-cookie-authentication","et-has-post-format-content","et_post_format-et-post-format-standard"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.7 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Cookie Authentication With ASP.NET Core and Angular - Code Maze<\/title>\n<meta name=\"description\" content=\"In this article, let&#039;s learn how to implement cookie authentication using ASP.NET Core and Angular with a detailed step by step guide.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Cookie Authentication With ASP.NET Core and Angular - Code Maze\" \/>\n<meta property=\"og:description\" content=\"In this article, let&#039;s learn how to implement cookie authentication using ASP.NET Core and Angular with a detailed step by step guide.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/\" \/>\n<meta property=\"og:site_name\" content=\"Code Maze\" \/>\n<meta property=\"article:published_time\" content=\"2022-07-18T06:41:53+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1100\" \/>\n\t<meta property=\"og:image:height\" content=\"620\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Code Maze\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/CodeMazeBlog\" \/>\n<meta name=\"twitter:site\" content=\"@CodeMazeBlog\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Code Maze\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":[\"Article\",\"BlogPosting\"],\"@id\":\"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/\"},\"author\":{\"name\":\"Code Maze\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/09d29b223012c8e94a68ba62861d0b04\"},\"headline\":\"Cookie Authentication With ASP.NET Core and Angular\",\"datePublished\":\"2022-07-18T06:41:53+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/\"},\"wordCount\":1193,\"commentCount\":9,\"publisher\":{\"@id\":\"https:\/\/code-maze.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png\",\"keywords\":[\"Angular\",\"asp.net core web api\",\"Cookie\",\"Cookie Authentication\"],\"articleSection\":[\"Angular\",\"HTTP\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/\",\"url\":\"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/\",\"name\":\"Cookie Authentication With ASP.NET Core and Angular - Code Maze\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png\",\"datePublished\":\"2022-07-18T06:41:53+00:00\",\"description\":\"In this article, let's learn how to implement cookie authentication using ASP.NET Core and Angular with a detailed step by step guide.\",\"breadcrumb\":{\"@id\":\"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/#primaryimage\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png\",\"width\":1100,\"height\":620,\"caption\":\"ASP.NET Core\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/code-maze.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Cookie Authentication With ASP.NET Core and Angular\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/code-maze.com\/#website\",\"url\":\"https:\/\/code-maze.com\/\",\"name\":\"Code Maze\",\"description\":\"Learn. Code. Succeed.\",\"publisher\":{\"@id\":\"https:\/\/code-maze.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/code-maze.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/code-maze.com\/#organization\",\"name\":\"Code Maze\",\"url\":\"https:\/\/code-maze.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png\",\"width\":3511,\"height\":3510,\"caption\":\"Code Maze\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/CodeMazeBlog\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/09d29b223012c8e94a68ba62861d0b04\",\"name\":\"Code Maze\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez-150x150.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez-150x150.png\",\"caption\":\"Code Maze\"},\"description\":\"This is the standard author on the site. Most articles are published by individual authors, with their profiles, but when several authors have contributed, we publish collectively as a part of this profile.\",\"sameAs\":[\"https:\/\/www.linkedin.com\/company\/codemaze\/\",\"https:\/\/x.com\/https:\/\/twitter.com\/CodeMazeBlog\"],\"url\":\"https:\/\/code-maze.com\/author\/codemazecontributor\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Cookie Authentication With ASP.NET Core and Angular - Code Maze","description":"In this article, let's learn how to implement cookie authentication using ASP.NET Core and Angular with a detailed step by step guide.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/","og_locale":"en_US","og_type":"article","og_title":"Cookie Authentication With ASP.NET Core and Angular - Code Maze","og_description":"In this article, let's learn how to implement cookie authentication using ASP.NET Core and Angular with a detailed step by step guide.","og_url":"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/","og_site_name":"Code Maze","article_published_time":"2022-07-18T06:41:53+00:00","og_image":[{"width":1100,"height":620,"url":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png","type":"image\/png"}],"author":"Code Maze","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/CodeMazeBlog","twitter_site":"@CodeMazeBlog","twitter_misc":{"Written by":"Code Maze","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":["Article","BlogPosting"],"@id":"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/#article","isPartOf":{"@id":"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/"},"author":{"name":"Code Maze","@id":"https:\/\/code-maze.com\/#\/schema\/person\/09d29b223012c8e94a68ba62861d0b04"},"headline":"Cookie Authentication With ASP.NET Core and Angular","datePublished":"2022-07-18T06:41:53+00:00","mainEntityOfPage":{"@id":"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/"},"wordCount":1193,"commentCount":9,"publisher":{"@id":"https:\/\/code-maze.com\/#organization"},"image":{"@id":"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png","keywords":["Angular","asp.net core web api","Cookie","Cookie Authentication"],"articleSection":["Angular","HTTP"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/","url":"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/","name":"Cookie Authentication With ASP.NET Core and Angular - Code Maze","isPartOf":{"@id":"https:\/\/code-maze.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/#primaryimage"},"image":{"@id":"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png","datePublished":"2022-07-18T06:41:53+00:00","description":"In this article, let's learn how to implement cookie authentication using ASP.NET Core and Angular with a detailed step by step guide.","breadcrumb":{"@id":"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/#primaryimage","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-aspnetcore.png","width":1100,"height":620,"caption":"ASP.NET Core"},{"@type":"BreadcrumbList","@id":"https:\/\/code-maze.com\/cookie-authentication-aspnetcore-angular\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/code-maze.com\/"},{"@type":"ListItem","position":2,"name":"Cookie Authentication With ASP.NET Core and Angular"}]},{"@type":"WebSite","@id":"https:\/\/code-maze.com\/#website","url":"https:\/\/code-maze.com\/","name":"Code Maze","description":"Learn. Code. Succeed.","publisher":{"@id":"https:\/\/code-maze.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/code-maze.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/code-maze.com\/#organization","name":"Code Maze","url":"https:\/\/code-maze.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/#\/schema\/logo\/image\/","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png","width":3511,"height":3510,"caption":"Code Maze"},"image":{"@id":"https:\/\/code-maze.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/CodeMazeBlog"]},{"@type":"Person","@id":"https:\/\/code-maze.com\/#\/schema\/person\/09d29b223012c8e94a68ba62861d0b04","name":"Code Maze","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/#\/schema\/person\/image\/","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez-150x150.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez-150x150.png","caption":"Code Maze"},"description":"This is the standard author on the site. Most articles are published by individual authors, with their profiles, but when several authors have contributed, we publish collectively as a part of this profile.","sameAs":["https:\/\/www.linkedin.com\/company\/codemaze\/","https:\/\/x.com\/https:\/\/twitter.com\/CodeMazeBlog"],"url":"https:\/\/code-maze.com\/author\/codemazecontributor\/"}]}},"_links":{"self":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/72457","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/comments?post=72457"}],"version-history":[{"count":2,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/72457\/revisions"}],"predecessor-version":[{"id":72459,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/72457\/revisions\/72459"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media\/62187"}],"wp:attachment":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media?parent=72457"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/categories?post=72457"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/tags?post=72457"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}