{"id":54392,"date":"2020-12-14T08:00:07","date_gmt":"2020-12-14T07:00:07","guid":{"rendered":"https:\/\/code-maze.com\/?p=54392"},"modified":"2022-05-17T11:22:53","modified_gmt":"2022-05-17T09:22:53","slug":"angular-authentication-aspnet-identity","status":"publish","type":"post","link":"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/","title":{"rendered":"Angular Authentication Functionality with ASP.NET Core Identity"},"content":{"rendered":"<p>Right now, we have a way to <a href=\"https:\/\/code-maze.com\/user-registration-angular-aspnet-identity\/\" target=\"_blank\" rel=\"noopener noreferrer\">register new users<\/a> in our application. But these users don\u2019t have the option to log in or log out from our application. So, creating Angular Authentication functionality (Login and Logout) will be the main goal for this article. As in the previous articles, we are going to use the ASP.NET Core Identity library to help us in the process.<\/p>\n<div style=\"padding: 20px; border-left: 5px #dc2323 solid; display: block; margin-bottom: 20px; box-shadow: 1px 1px 5px 0px lightgrey;\">You can download the source code by visiting our <a href=\"https:\/\/github.com\/CodeMazeBlog\/angular-identity-aspnetcore-security\/tree\/angular-authentication-identity\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Angular Authentication Functionality<\/a> repository.<\/div>\n<p>For complete navigation through the entire series, you can visit the <a href=\"https:\/\/code-maze.com\/angular-security-with-asp-net-core-identity\/\" target=\"_blank\" rel=\"noopener noreferrer\">Angular with ASP.NET Core Identity<\/a> page.<\/p>\n<p>Let&#8217;s get going.<\/p>\n<h2 id=\"integrating-jwt\">Integrating JWT in the Web API Project<\/h2>\n<p>We are going to use tokens to transfer information to the client-side application and back to the server-side. So for that, we have to integrate JWT into our Web API application.<\/p>\n<p>We won\u2019t dive deep into the JWT explanations because we have detailed articles related to that topic (Jwt Authentication <a href=\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/\" target=\"_blank\" rel=\"noopener noreferrer\">Part1<\/a>, <a href=\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-2\/\" target=\"_blank\" rel=\"noopener noreferrer\">Part2<\/a>, <a href=\"https:\/\/code-maze.com\/using-refresh-tokens-in-asp-net-core-authentication\/\" target=\"_blank\" rel=\"noopener noreferrer\">Part3<\/a>). So, if you want to read more about JWT, feel free to read them.<\/p>\n<p>That said, let\u2019s start by installing the <code>Microsoft.AspNetCore.Authentication.JwtBearer<\/code> library in the main project:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/15-Jwt-Library-installation.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-54393 size-full\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/15-Jwt-Library-installation-e1652274258738.png\" alt=\" Jwt Library installation\" width=\"411\" height=\"46\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/15-Jwt-Library-installation-e1652274258738.png 411w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/15-Jwt-Library-installation-e1652274258738-300x34.png 300w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/15-Jwt-Library-installation-e1652274258738-400x46.png 400w\" sizes=\"auto, (max-width: 411px) 100vw, 411px\" \/><\/a><\/p>\n<p>After the installation, we are going to add the configuration parameters in the <code>appsettings.json<\/code> file:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"json\" data-enlighter-highlight=\"12-17\">{\r\n  \"Logging\": {\r\n    \"LogLevel\": {\r\n      \"Default\": \"Information\",\r\n      \"Microsoft\": \"Warning\"\r\n    }\r\n  },\r\n  \"ConnectionStrings\": {\r\n    \"sqlConnection\": \"server=.; database=CompanyEmployees; Integrated Security=true\"\r\n  },\r\n  \"JWTSettings\": {\r\n    \"securityKey\": \"CodeMazeSecretKey\",\r\n    \"validIssuer\": \"CodeMazeAPI\",\r\n    \"validAudience\": \"https:\/\/localhost:5011\",\r\n    \"expiryInMinutes\": 5\r\n  },\r\n  \"AllowedHosts\": \"*\"\r\n}\r\n<\/pre>\n<p>Then, let\u2019s modify the <span style=\"color: #222222; font-family: monospace;\"><span style=\"background-color: #e9ebec;\">Program<\/span><\/span> class and register the JWT authentication right below the <code>AddEntityFrameworkStores&lt;RepositoryContext&gt;()<\/code> method:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">var jwtSettings = builder.Configuration.GetSection(\"JwtSettings\");\r\nbuilder.Services.AddAuthentication(opt =&gt;\r\n{\r\n    opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;\r\n    opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;\r\n}).AddJwtBearer(options =&gt;\r\n{\r\n    options.TokenValidationParameters = new TokenValidationParameters\r\n    {\r\n        ValidateIssuer = true,\r\n        ValidateAudience = true,\r\n        ValidateLifetime = true,\r\n        ValidateIssuerSigningKey = true,\r\n        ValidIssuer = jwtSettings[\"validIssuer\"],\r\n        ValidAudience = jwtSettings[\"validAudience\"],\r\n        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8\r\n            .GetBytes(jwtSettings.GetSection(\"securityKey\").Value))\r\n    };\r\n});<\/pre>\n<p>Also, we have to\u00a0add Authentication and Authorization to the request pipeline:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-highlight=\"3-4\">app.UseAuthentication();\r\napp.UseAuthorization();\r\n<\/pre>\n<p>Lastly, let\u2019s protect the <code>CompaniesController<\/code> from unauthorized access:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-highlight=\"2\">[Route(\"api\/companies\")]\r\n[Authorize]\r\n[ApiController]\r\npublic class CompaniesController : ControllerBase\r\n<\/pre>\n<p>That\u2019s all we need.<\/p>\n<p>We can move on to the Login implementation.<\/p>\n<h2 id=\"web-api-login\">Web API\u2019s Login Implementation<\/h2>\n<p>Before we start working on the Angular authentication functionality, we need to have a server-side logic to handle the authentication request.<\/p>\n<p>That said, let\u2019s start with two DTO classes inside the <code>Entities\/DataTransferObjects<\/code> folder:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public class UserForAuthenticationDto\r\n{\r\n    [Required(ErrorMessage = \"Email is required.\")]\r\n    public string? Email { get; set; }\r\n    [Required(ErrorMessage = \"Password is required.\")]\r\n    public string? Password { get; set; }\r\n}\r\n\r\npublic class AuthResponseDto\r\n{\r\n    public bool IsAuthSuccessful { get; set; }\r\n    public string? ErrorMessage { get; set; }\r\n    public string? Token { get; set; }\r\n}\r\n<\/pre>\n<p>Now, we are going to create a new <code>JwtFeatures<\/code> folder and inside a new <code>JwtHandler<\/code> class:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public class JwtHandler\r\n{\r\n    private readonly IConfiguration _configuration;\r\n    private readonly IConfigurationSection _jwtSettings;\r\n\r\n    public JwtHandler(IConfiguration configuration)\r\n    {\r\n        _configuration = configuration;\r\n        _jwtSettings = _configuration.GetSection(\"JwtSettings\");\r\n    }\r\n\r\n    public SigningCredentials GetSigningCredentials()\r\n    {\r\n        var key = Encoding.UTF8.GetBytes(_jwtSettings.GetSection(\"securityKey\").Value);\r\n        var secret = new SymmetricSecurityKey(key);\r\n\r\n        return new SigningCredentials(secret, SecurityAlgorithms.HmacSha256);\r\n    }\r\n\r\n    public List&lt;Claim&gt; GetClaims(IdentityUser user)\r\n    {\r\n        var claims = new List&lt;Claim&gt;\r\n        {\r\n            new Claim(ClaimTypes.Name, user.Email)\r\n        };\r\n\r\n        return claims;\r\n    }\r\n\r\n    public JwtSecurityToken GenerateTokenOptions(SigningCredentials signingCredentials, List&lt;Claim&gt; claims)\r\n    {\r\n        var tokenOptions = new JwtSecurityToken(\r\n            issuer: _jwtSettings[\"validIssuer\"],\r\n            audience: _jwtSettings[\"validAudience\"],\r\n            claims: claims,\r\n            expires: DateTime.Now.AddMinutes(Convert.ToDouble(_jwtSettings[\"expiryInMinutes\"])),\r\n            signingCredentials: signingCredentials);\r\n\r\n        return tokenOptions;\r\n    }\r\n}<\/pre>\n<p>In this class, we create several methods to help us with the authentication process. We fetch the SigningCredentials, the list of claims, and create a JwtSecurityToken. Again all of these are explained in our <a href=\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/\" target=\"_blank\" rel=\"noopener noreferrer\">Jwt with ASP.NET Core<\/a> article.<\/p>\n<p>To continue, we can register <code>JwtHandler<\/code> as a service:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">builder.Services.AddScoped&lt;JwtHandler&gt;();<\/code><\/p>\n<p>After that, we can inject this service inside the <code>AccountsController<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-highlight=\"3,5,9\">private readonly UserManager&lt;User&gt; _userManager; \r\nprivate readonly IMapper _mapper;\r\nprivate readonly JwtHandler _jwtHandler;\r\n\r\npublic AccountsController(UserManager&lt;User&gt; userManager, IMapper mapper, JwtHandler jwtHandler) \r\n{\r\n    _userManager = userManager;\r\n    _mapper = mapper;\r\n    _jwtHandler = jwtHandler;\r\n}\r\n<\/pre>\n<p>And we can add the <code>Login<\/code> action to the same controller:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">[HttpPost(\"Login\")]\r\npublic async Task&lt;IActionResult&gt; Login([FromBody] UserForAuthenticationDto userForAuthentication)\r\n{\r\n    var user = await _userManager.FindByNameAsync(userForAuthentication.Email);\r\n\r\n    if (user == null || !await _userManager.CheckPasswordAsync(user, userForAuthentication.Password))\r\n        return Unauthorized(new AuthResponseDto { ErrorMessage = \"Invalid Authentication\" });\r\n\r\n    var signingCredentials = _jwtHandler.GetSigningCredentials();\r\n    var claims = _jwtHandler.GetClaims(user);\r\n    var tokenOptions = _jwtHandler.GenerateTokenOptions(signingCredentials, claims);\r\n    var token = new JwtSecurityTokenHandler().WriteToken(tokenOptions);\r\n\r\n    return Ok(new AuthResponseDto { IsAuthSuccessful = true, Token = token });\r\n}\r\n<\/pre>\n<p>With the help of <code>UserManager<\/code>, we fetch the user by calling the <code>FindByNameAsync<\/code> method. If the user doesn\u2019t exist, we return an unauthorized response. Otherwise, we use our <code>JwtHandler<\/code> class to get all the information we require, create a token and return it as a part of our response.<\/p>\n<p>Now, we can test this functionality:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/16-Authentication-Successfull-with-token.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-54394\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/16-Authentication-Successfull-with-token.png\" alt=\"Authentication Successfull with token\" width=\"796\" height=\"317\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/16-Authentication-Successfull-with-token.png 796w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/16-Authentication-Successfull-with-token-300x119.png 300w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/16-Authentication-Successfull-with-token-768x306.png 768w\" sizes=\"auto, (max-width: 796px) 100vw, 796px\" \/><\/a><\/p>\n<p>With this out of the way, we can move on to the Angular authentication functionality.<\/p>\n<h2 id=\"angular-login-action\">Angular Authentication Functionality \u2013 Creating the Login Action<\/h2>\n<p>Let\u2019s start with the interface creation.<\/p>\n<p>In the <code>_interfaces\/user<\/code> folder, we are going to create the <code>userForAuthenticationDto<\/code> interface:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">export interface UserForAuthenticationDto {\r\n    email: string;\r\n    password: string;\r\n}\r\n<\/pre>\n<p>We need one more interface under the <code>_interfaces\/response<\/code> folder:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">export interface AuthResponseDto {\r\n    isAuthSuccessful: boolean;\r\n    errorMessage: string;\r\n    token: string;\r\n}\r\n<\/pre>\n<p>After this, we have to modify the <code>authentication.service.ts<\/code> file by adding a new <code>loginUser<\/code> function:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">public loginUser = (route: string, body: UserForAuthenticationDto) =&gt; {\r\n  return this.http.post&lt;AuthResponseDto&gt;(this.createCompleteRoute(route, this.envUrl.urlAddress), body);\r\n}\r\n<\/pre>\n<p>Now, we are going to create the Login component files:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">ng g c authentication\/login --skip-tests<\/pre>\n<p>Before we move on with the Login component implementation, let\u2019s add the route to this component inside the <code>authentication.module.ts<\/code> file:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-highlight=\"3\">RouterModule.forChild([\r\n  { path: 'register', component: RegisterUserComponent },\r\n  { path: 'login', component: LoginComponent }\r\n])\r\n<\/pre>\n<p>Excellent.<\/p>\n<p>We are ready to modify the <code>login.component.ts<\/code> file:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">import { HttpErrorResponse } from '@angular\/common\/http';\r\nimport { AuthResponseDto } from '.\/..\/..\/_interfaces\/response\/authResponseDto.model';\r\nimport { UserForAuthenticationDto } from '.\/..\/..\/_interfaces\/user\/userForAuthenticationDto.model';\r\nimport { Router, ActivatedRoute } from '@angular\/router';\r\nimport { AuthenticationService } from '.\/..\/..\/shared\/services\/authentication.service';\r\nimport { Component, OnInit } from '@angular\/core';\r\nimport { FormGroup, FormControl, Validators } from '@angular\/forms';\r\n\r\n@Component({\r\n  selector: 'app-login',\r\n  templateUrl: '.\/login.component.html',\r\n  styleUrls: ['.\/login.component.css']\r\n})\r\nexport class LoginComponent implements OnInit {\r\n  private returnUrl: string;\r\n  \r\n  loginForm: FormGroup;\r\n  errorMessage: string = '';\r\n  showError: boolean;\r\n\r\n  constructor(private authService: AuthenticationService, private router: Router, private route: ActivatedRoute) { }\r\n  \r\n  ngOnInit(): void {\r\n    this.loginForm = new FormGroup({\r\n      username: new FormControl(\"\", [Validators.required]),\r\n      password: new FormControl(\"\", [Validators.required])\r\n    })\r\n    this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '\/';\r\n  }\r\n\r\n  validateControl = (controlName: string) =&gt; {\r\n    return this.loginForm.get(controlName).invalid &amp;&amp; this.loginForm.get(controlName).touched\r\n  }\r\n\r\n  hasError = (controlName: string, errorName: string) =&gt; {\r\n    return this.loginForm.get(controlName).hasError(errorName)\r\n  }\r\n  \r\n  loginUser = (loginFormValue) =&gt; {\r\n    this.showError = false;\r\n    const login = {... loginFormValue };\r\n\r\n    const userForAuth: UserForAuthenticationDto = {\r\n      email: login.username,\r\n      password: login.password\r\n    }\r\n\r\n    this.authService.loginUser('api\/accounts\/login', userForAuth)\r\n    .subscribe({\r\n      next: (res:AuthResponseDto) =&gt; {\r\n       localStorage.setItem(\"token\", res.token);\r\n       this.router.navigate([this.returnUrl]);\r\n    },\r\n    error: (err: HttpErrorResponse) =&gt; {\r\n      this.errorMessage = err.message;\r\n      this.showError = true;\r\n    }})\r\n  }\r\n}<\/pre>\n<p>Here, we create the <code>FormGroup<\/code> object populated with both controls. Also, we create the <code>returnUrl<\/code> parameter to navigate the user to the requested location once they log in successfully. The <code>validateControl<\/code> and <code>hasError<\/code> functions are familiar ones. Since these two functions repeat in both the register and login components, you can extract them to a separate class. For the sake of simplicity, we are going to leave this implementation as-is.<\/p>\n<p>In the <code>loginUser<\/code> function, we extract the value from the Login form and send the request to the API. If it is successful, we store the token in the local storage and redirect the user. Otherwise, we just show the error message.<\/p>\n<p>Of course, we have to modify the <code>login.component.html<\/code> file:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\">&lt;div class=\"card\"&gt;\r\n  &lt;div class=\"card-body\"&gt;\r\n      &lt;h1 class=\"card-title\"&gt;Login&lt;\/h1&gt;\r\n\r\n      &lt;div *ngIf=\"showError\" class=\"alert alert-danger\" role=\"alert\"&gt;\r\n          {{errorMessage}}\r\n      &lt;\/div&gt;\r\n      \r\n      &lt;form [formGroup]=\"loginForm\" autocomplete=\"off\" novalidate (ngSubmit)=\"loginUser(loginForm.value)\"&gt;\r\n          &lt;div class=\"mb-3 row\"&gt;\r\n              &lt;label for=\"username\" class=\"col-form-label col-sm-2\"&gt;Username:&lt;\/label&gt;\r\n              &lt;div class=\"col-md-5\"&gt;\r\n                  &lt;input type=\"text\" id=\"username\" formControlName=\"username\" class=\"form-control\" \/&gt;\r\n              &lt;\/div&gt;\r\n              &lt;div class=\"col-md-5\"&gt;\r\n                  &lt;em *ngIf=\"validateControl('username') &amp;&amp; hasError('username', 'required')\"&gt;Username is required&lt;\/em&gt;\r\n              &lt;\/div&gt;\r\n          &lt;\/div&gt;\r\n          &lt;div class=\"mb-3 row\"&gt;\r\n              &lt;label for=\"password\" class=\"col-form-label col-sm-2\"&gt;Password:&lt;\/label&gt;\r\n              &lt;div class=\"col-md-5\"&gt;\r\n                  &lt;input type=\"password\" id=\"password\" formControlName=\"password\" class=\"form-control\" \/&gt;\r\n              &lt;\/div&gt;\r\n              &lt;div class=\"col-md-5\"&gt;\r\n                  &lt;em *ngIf=\"validateControl('password') &amp;&amp; hasError('password', 'required')\"&gt;Password is required&lt;\/em&gt;\r\n              &lt;\/div&gt;\r\n          &lt;\/div&gt;\r\n          &lt;br&gt;\r\n          &lt;div class=\"mb-3 row\"&gt;\r\n              &lt;div class=\"col-md-1\"&gt;\r\n                  &lt;button type=\"submit\" class=\"btn btn-info\" [disabled]=\"!loginForm.valid\"&gt;Login&lt;\/button&gt;\r\n              &lt;\/div&gt;\r\n          &lt;\/div&gt;\r\n      &lt;\/form&gt;\r\n  &lt;\/div&gt;\r\n&lt;\/div&gt;<\/pre>\n<p>This is a familiar code, with two controls and the Login button.<\/p>\n<h3>Testing the Login Functionality<\/h3>\n<p>Let\u2019s start the API and the Angular application. Then, we have to navigate to the <code>http:\/\/localhost:4200\/authentication\/login<\/code> because we don\u2019t have the login link yet:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/17-Angular-Authentication-Login-Page.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-54395 size-full\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/17-Angular-Authentication-Login-Page.png\" alt=\"Angular Authentication Functionality - Login Page\" width=\"545\" height=\"355\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/17-Angular-Authentication-Login-Page.png 545w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/17-Angular-Authentication-Login-Page-300x195.png 300w\" sizes=\"auto, (max-width: 545px) 100vw, 545px\" \/><\/a><\/p>\n<p>If we try to leave these controls empty, we are going to see validation messages:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/18-Angular-Authentication-Validation-Messages.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-54396\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/18-Angular-Authentication-Validation-Messages.png\" alt=\"Angular Authentication Validation Messages\" width=\"714\" height=\"236\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/18-Angular-Authentication-Validation-Messages.png 714w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/18-Angular-Authentication-Validation-Messages-300x99.png 300w\" sizes=\"auto, (max-width: 714px) 100vw, 714px\" \/><\/a><\/p>\n<p>But, if we enter valid credentials, the application navigates us to the Home page with the token stored in the Local Storage:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/19-Successful-Angular-Authentication-with-Token-in-Local-Storage.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-54397\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/19-Successful-Angular-Authentication-with-Token-in-Local-Storage.png\" alt=\"Successful Angular Authentication with Token in Local Storage\" width=\"976\" height=\"369\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/19-Successful-Angular-Authentication-with-Token-in-Local-Storage.png 976w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/19-Successful-Angular-Authentication-with-Token-in-Local-Storage-300x113.png 300w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/19-Successful-Angular-Authentication-with-Token-in-Local-Storage-768x290.png 768w\" sizes=\"auto, (max-width: 976px) 100vw, 976px\" \/><\/a><\/p>\n<p>The login action works, but we still have tasks to complete.<\/p>\n<h2 id=\"modifying-menu\">Modifying Menu After the Angular Authentication State Changes<\/h2>\n<p>Right now, we only have the Register link displayed on the navigation menu. But what we want is to display the Login and Register buttons if the user is not authenticated and otherwise to display the Logout button.<\/p>\n<p>To do that, we are going to start with <code>authentication.service.ts<\/code> file modification.<\/p>\n<p>First, let\u2019s create an observable to notify all the subscribed components about the Angular authentication state change:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-highlight=\"2,7-8,12-14\">...\r\nimport { Subject } from 'rxjs';\r\n@Injectable({\r\n  providedIn: 'root'\r\n})\r\nexport class AuthenticationService {\r\n  private authChangeSub = new Subject&lt;boolean&gt;()\r\n  public authChanged = this.authChangeSub.asObservable();\r\n  \r\n  constructor(private http: HttpClient, private envUrl: EnvironmentUrlService) { }\r\n  ...\r\n  public sendAuthStateChangeNotification = (isAuthenticated: boolean) =&gt; {\r\n    this.authChangeSub.next(isAuthenticated);\r\n  }\r\n  private createCompleteRoute = (route: string, envAddress: string) =&gt; {\r\n    return `${envAddress}\/${route}`;\r\n  }\r\n}\r\n<\/pre>\n<p>With this in place, we can modify the <code>loginUser<\/code> function:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-highlight=\"4\">.subscribe({\r\n      next: (res:AuthResponseDto) =&gt; {\r\n       localStorage.setItem(\"token\", res.token);\r\n       this.authService.sendAuthStateChangeNotification(res.isAuthSuccessful);\r\n       this.router.navigate([this.returnUrl]);\r\n    },<\/pre>\n<p>Here, we send the notification to the subscribed components.<\/p>\n<p>Now, let\u2019s continue with the <code>menu.component.ts<\/code> modification:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-highlight=\"1,10,12,15-18\">import { AuthenticationService } from '.\/..\/shared\/services\/authentication.service';\r\nimport { Component, OnInit } from '@angular\/core';\r\n\r\n@Component({\r\n  selector: 'app-menu',\r\n  templateUrl: '.\/menu.component.html',\r\n  styleUrls: ['.\/menu.component.css']\r\n})\r\nexport class MenuComponent implements OnInit {\r\n  public isUserAuthenticated: boolean;\r\n\r\n  constructor(private authService: AuthenticationService) { }\r\n\r\n  ngOnInit(): void {\r\n    this.authService.authChanged\r\n    .subscribe(res =&gt; {\r\n      this.isUserAuthenticated = res;\r\n    })\r\n  }\r\n\r\n}<\/pre>\n<p>We inject the Authentication service and subscribe to the observable notification sent from that service.<\/p>\n<p>Now, we can modify the <code>menu.component.html<\/code> file:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\">&lt;form class=\"form-inline my-2 my-lg-0\"&gt;\r\n  &lt;ul *ngIf='!isUserAuthenticated' class=\"navbar-nav mr-auto mt-2 mt-lg-0\"&gt;\r\n    &lt;li class=\"nav-item\"&gt;\r\n      &lt;a class=\"nav-link\"[routerLink]=\"['\/authentication\/login']\" routerLinkActive=\"active\" \r\n        [routerLinkActiveOptions]=\"{exact: true}\"&gt;Login&lt;\/a&gt;\r\n    &lt;\/li&gt;\r\n    &lt;li class=\"nav-item\"&gt;\r\n      &lt;a class=\"nav-link\"[routerLink]=\"['\/authentication\/register']\" routerLinkActive=\"active\" \r\n        [routerLinkActiveOptions]=\"{exact: true}\"&gt;Register&lt;\/a&gt;\r\n    &lt;\/li&gt;\r\n  &lt;\/ul&gt;\r\n  &lt;ul *ngIf='isUserAuthenticated' class=\"navbar-nav mr-auto mt-2 mt-lg-0\"&gt;\r\n    &lt;li class=\"nav-item\"&gt;\r\n      &lt;button class=\"btn btn-link\" style=\"color: #ffffff80;\"&gt;Logout&lt;\/button&gt;\r\n    &lt;\/li&gt;\r\n  &lt;\/ul&gt;\r\n&lt;\/form&gt;\r\n<\/pre>\n<p>And that\u2019s it.<\/p>\n<p>If we log in successfully, we are going to see the Logout button for sure:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/20-Logout-button-displays-after-successful-authentication.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-54398\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/20-Logout-button-displays-after-successful-authentication.png\" alt=\"Logout button displays after successful authentication\" width=\"916\" height=\"131\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/20-Logout-button-displays-after-successful-authentication.png 916w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/20-Logout-button-displays-after-successful-authentication-300x43.png 300w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/20-Logout-button-displays-after-successful-authentication-768x110.png 768w\" sizes=\"auto, (max-width: 916px) 100vw, 916px\" \/><\/a><\/p>\n<p>Great job.<\/p>\n<h3>Modifying Registration Logic<\/h3>\n<p>Since we have the Login component in place, we don\u2019t have to log the success message after successful registration, we can navigate to the Login page.<\/p>\n<p>All we have to do is to inject the Router class in the <code>register-user.component.ts<\/code> file:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">constructor(private authService: AuthenticationService, private passConfValidator: PasswordConfirmationValidatorService,\r\n    private router: Router) { }\r\n<\/pre>\n<p>And to modify the subscribe part of the <code>registerUser<\/code> function:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">next: (_) =&gt; this.router.navigate([\"\/authentication\/login\"]),<\/code><\/p>\n<p>As you can see, it doesn\u2019t get easier than that.<\/p>\n<p>We can move on to the Logout implementation.<\/p>\n<h2 id=\"angular-logout\">Angular Authentication Functionality &#8211; Implementing the Logout Action<\/h2>\n<p>To implement the Logout action in our Angular application, we have to add a new function in the Authentication service:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">public logout = () =&gt; {\r\n  localStorage.removeItem(\"token\");\r\n  this.sendAuthStateChangeNotification(false);\r\n}\r\n<\/pre>\n<p>Here, we just remove the token from the storage and send an authentication change notification to the subscribed components (in this case only the menu component).<\/p>\n<p>That said, we are going to modify the <code>menu.component.ts<\/code> file:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-highlight=\"1,10-13\">constructor(private authService: AuthenticationService, private router: Router) { }\r\n\r\nngOnInit(): void {\r\n  this.authService.authChanged\r\n  .subscribe(res =&gt; {\r\n    this.isUserAuthenticated = res;\r\n  })\r\n}\r\n\r\npublic logout = () =&gt; {\r\n  this.authService.logout();\r\n  this.router.navigate([\"\/\"]);\r\n}\r\n<\/pre>\n<p>And finally, we have to modify the HTML file:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\">&lt;ul *ngIf='isUserAuthenticated' class=\"navbar-nav mr-auto mt-2 mt-lg-0\"&gt;\r\n  &lt;li class=\"nav-item\"&gt;\r\n    &lt;button class=\"btn btn-link\" style=\"color: #ffffff80;\" (click)=\"logout()\"&gt;Logout&lt;\/button&gt;\r\n  &lt;\/li&gt;\r\n&lt;\/ul&gt;\r\n<\/pre>\n<p>That\u2019s it.<\/p>\n<p>Now, as soon as we click the Logout link, the token will be removed from the storage, the Logout link will disappear and our application will redirect the user to the Home page:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/21-Successful-Logout-Action.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-54399\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/21-Successful-Logout-Action.png\" alt=\"Successful Logout Action\" width=\"963\" height=\"372\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/21-Successful-Logout-Action.png 963w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/21-Successful-Logout-Action-300x116.png 300w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/21-Successful-Logout-Action-768x297.png 768w\" sizes=\"auto, (max-width: 963px) 100vw, 963px\" \/><\/a><\/p>\n<p>Let\u2019s move on.<\/p>\n<h2 id=\"angular-errors\">Handling Angular Authentication Errors<\/h2>\n<p>We have working Login and Logout actions prepared for the Angular Authentication process, but there are still missing pieces. One of those is error handling and showing an error message on the Login page.<\/p>\n<p>We are going to handle the rest of the missing pieces in the next article (Roles, Guards, Refresh app state&#8230;).<\/p>\n<p>If we try to log in with invalid credentials, we are going to see a red empty square on the page:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/22-Angular-Authentication-with-wrong-credentials.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-54400 size-full\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/22-Angular-Authentication-with-wrong-credentials.png\" alt=\"Angular Authentication Functionality with wrong credentials\" width=\"654\" height=\"423\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/22-Angular-Authentication-with-wrong-credentials.png 654w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/08\/22-Angular-Authentication-with-wrong-credentials-300x194.png 300w\" sizes=\"auto, (max-width: 654px) 100vw, 654px\" \/><\/a><\/p>\n<p>Right away, we can see why the error message is not displayed on the page. It&#8217;s because we only handle the 404 and 400 errors, and this error is 401 \u2013 Unauthorized.<\/p>\n<p>To fix this, we have to modify the <code>error-handler.service.ts<\/code> file:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-highlight=\"7-9,13-21\">private handleError = (error: HttpErrorResponse) : string =&gt; {\r\n  if(error.status === 404) {\r\n    return this.handleNotFound(error);\r\n  }\r\n  else if(error.status === 400) {\r\n    return this.handleBadRequest(error);\r\n  }\r\n  else if(error.status === 401) {\r\n    return this.handleUnauthorized(error);\r\n  }\r\n}\r\n\r\nprivate handleUnauthorized = (error: HttpErrorResponse) =&gt; {\r\n  if(this.router.url === '\/authentication\/login') {\r\n    return 'Authentication failed. Wrong Username or Password';\r\n  }\r\n  else {\r\n    this._router.navigate(['\/authentication\/login']);\r\n    return error.message;\r\n  }\r\n}\r\n<\/pre>\n<p>If our service intercepts the response with the 401 error message, it will check whether we are already on the Login page or not. If we are on the Login page, we just return the error message. Otherwise, we redirect the user to the Login page.<\/p>\n<p>Now if we test this:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/12\/23-Angular-Authentication-Failed-but-with-proper-error-message.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-56724 size-full\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/12\/23-Angular-Authentication-Failed-but-with-proper-error-message.png\" alt=\"Angular Authentication Failed but with proper error message\" width=\"732\" height=\"523\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/12\/23-Angular-Authentication-Failed-but-with-proper-error-message.png 732w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/12\/23-Angular-Authentication-Failed-but-with-proper-error-message-300x214.png 300w\" sizes=\"auto, (max-width: 732px) 100vw, 732px\" \/><\/a><\/p>\n<p>We can see the error message in place.<\/p>\n<p>Nicely done.<\/p>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>We could say that we have everything in place regarding the Login and Logout actions and partially we would be right. We have implemented a lot of actions in this article but there are still things that need to be covered.<\/p>\n<p>So, <a href=\"https:\/\/code-maze.com\/angular-role-based-authorization-with-aspnet-identity\/\" target=\"_blank\" rel=\"noopener noreferrer\">in the next article<\/a>, we are going to learn how to work with Roles, how to protect our routes with Guards, and also how to preserve Angular Authentication state upon the application refresh.<\/p>\n<p>As you can see a lot more to work with.<\/p>\n<p>That said, see you in the next article.<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Right now, we have a way to register new users in our application. But these users don\u2019t have the option to log in or log out from our application. So, creating Angular Authentication functionality (Login and Logout) will be the main goal for this article. As in the previous articles, we are going to use [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":56726,"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,12],"tags":[750,739,740],"class_list":["post-54392","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-angular","category-csharp","tag-angular-authentication","tag-login","tag-logout","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>Angular Authentication Functionality with ASP.NET Core Identity<\/title>\n<meta name=\"description\" content=\"In this article, we are going to learn how to implement Angular Authentication functionality including the Login and Logout actions.\" \/>\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\/angular-authentication-aspnet-identity\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Angular Authentication Functionality with ASP.NET Core Identity\" \/>\n<meta property=\"og:description\" content=\"In this article, we are going to learn how to implement Angular Authentication functionality including the Login and Logout actions.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/\" \/>\n<meta property=\"og:site_name\" content=\"Code Maze\" \/>\n<meta property=\"article:published_time\" content=\"2020-12-14T07:00:07+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-05-17T09:22:53+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/12\/Angular-Authentication.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=\"Marinko Spasojevi\u0107\" \/>\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=\"Marinko Spasojevi\u0107\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":[\"Article\",\"BlogPosting\"],\"@id\":\"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/\"},\"author\":{\"name\":\"Marinko Spasojevi\u0107\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/d6fa06e66820968d19b39fb63cff2533\"},\"headline\":\"Angular Authentication Functionality with ASP.NET Core Identity\",\"datePublished\":\"2020-12-14T07:00:07+00:00\",\"dateModified\":\"2022-05-17T09:22:53+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/\"},\"wordCount\":1337,\"commentCount\":24,\"publisher\":{\"@id\":\"https:\/\/code-maze.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/12\/Angular-Authentication.png\",\"keywords\":[\"Angular Authentication\",\"Login\",\"Logout\"],\"articleSection\":[\"Angular\",\"C#\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/\",\"url\":\"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/\",\"name\":\"Angular Authentication Functionality with ASP.NET Core Identity\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/12\/Angular-Authentication.png\",\"datePublished\":\"2020-12-14T07:00:07+00:00\",\"dateModified\":\"2022-05-17T09:22:53+00:00\",\"description\":\"In this article, we are going to learn how to implement Angular Authentication functionality including the Login and Logout actions.\",\"breadcrumb\":{\"@id\":\"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/#primaryimage\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/12\/Angular-Authentication.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/12\/Angular-Authentication.png\",\"width\":1100,\"height\":620,\"caption\":\"Angular Authentication with ASP.NET Core Identity\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/code-maze.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Angular Authentication Functionality with ASP.NET Core Identity\"}]},{\"@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\/d6fa06e66820968d19b39fb63cff2533\",\"name\":\"Marinko Spasojevi\u0107\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/marinko-1x1-3-150x150.jpg\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/marinko-1x1-3-150x150.jpg\",\"caption\":\"Marinko Spasojevi\u0107\"},\"description\":\"Hi, my name is Marinko Spasojevic. Currently, I work as a full-time .NET developer and my passion is web application development. Just getting something to work is not enough for me. To make it just how I like it, it must be readable, reusable, and easy to maintain. Prior to being an author on the CodeMaze blog, I had been working as a professor of Computer Science for several years. So, sharing knowledge while working as a full-time developer comes naturally to me.\",\"sameAs\":[\"https:\/\/www.linkedin.com\/in\/marinko-spasojevic\/\",\"https:\/\/x.com\/https:\/\/twitter.com\/CodeMazeBlog\"],\"url\":\"https:\/\/code-maze.com\/author\/marinko\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Angular Authentication Functionality with ASP.NET Core Identity","description":"In this article, we are going to learn how to implement Angular Authentication functionality including the Login and Logout actions.","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\/angular-authentication-aspnet-identity\/","og_locale":"en_US","og_type":"article","og_title":"Angular Authentication Functionality with ASP.NET Core Identity","og_description":"In this article, we are going to learn how to implement Angular Authentication functionality including the Login and Logout actions.","og_url":"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/","og_site_name":"Code Maze","article_published_time":"2020-12-14T07:00:07+00:00","article_modified_time":"2022-05-17T09:22:53+00:00","og_image":[{"width":1100,"height":620,"url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/12\/Angular-Authentication.png","type":"image\/png"}],"author":"Marinko Spasojevi\u0107","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/CodeMazeBlog","twitter_site":"@CodeMazeBlog","twitter_misc":{"Written by":"Marinko Spasojevi\u0107","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":["Article","BlogPosting"],"@id":"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/#article","isPartOf":{"@id":"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/"},"author":{"name":"Marinko Spasojevi\u0107","@id":"https:\/\/code-maze.com\/#\/schema\/person\/d6fa06e66820968d19b39fb63cff2533"},"headline":"Angular Authentication Functionality with ASP.NET Core Identity","datePublished":"2020-12-14T07:00:07+00:00","dateModified":"2022-05-17T09:22:53+00:00","mainEntityOfPage":{"@id":"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/"},"wordCount":1337,"commentCount":24,"publisher":{"@id":"https:\/\/code-maze.com\/#organization"},"image":{"@id":"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/12\/Angular-Authentication.png","keywords":["Angular Authentication","Login","Logout"],"articleSection":["Angular","C#"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/","url":"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/","name":"Angular Authentication Functionality with ASP.NET Core Identity","isPartOf":{"@id":"https:\/\/code-maze.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/#primaryimage"},"image":{"@id":"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/12\/Angular-Authentication.png","datePublished":"2020-12-14T07:00:07+00:00","dateModified":"2022-05-17T09:22:53+00:00","description":"In this article, we are going to learn how to implement Angular Authentication functionality including the Login and Logout actions.","breadcrumb":{"@id":"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/#primaryimage","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/12\/Angular-Authentication.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/12\/Angular-Authentication.png","width":1100,"height":620,"caption":"Angular Authentication with ASP.NET Core Identity"},{"@type":"BreadcrumbList","@id":"https:\/\/code-maze.com\/angular-authentication-aspnet-identity\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/code-maze.com\/"},{"@type":"ListItem","position":2,"name":"Angular Authentication Functionality with ASP.NET Core Identity"}]},{"@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\/d6fa06e66820968d19b39fb63cff2533","name":"Marinko Spasojevi\u0107","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/#\/schema\/person\/image\/","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/marinko-1x1-3-150x150.jpg","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/marinko-1x1-3-150x150.jpg","caption":"Marinko Spasojevi\u0107"},"description":"Hi, my name is Marinko Spasojevic. Currently, I work as a full-time .NET developer and my passion is web application development. Just getting something to work is not enough for me. To make it just how I like it, it must be readable, reusable, and easy to maintain. Prior to being an author on the CodeMaze blog, I had been working as a professor of Computer Science for several years. So, sharing knowledge while working as a full-time developer comes naturally to me.","sameAs":["https:\/\/www.linkedin.com\/in\/marinko-spasojevic\/","https:\/\/x.com\/https:\/\/twitter.com\/CodeMazeBlog"],"url":"https:\/\/code-maze.com\/author\/marinko\/"}]}},"_links":{"self":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/54392","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\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/comments?post=54392"}],"version-history":[{"count":2,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/54392\/revisions"}],"predecessor-version":[{"id":70376,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/54392\/revisions\/70376"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media\/56726"}],"wp:attachment":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media?parent=54392"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/categories?post=54392"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/tags?post=54392"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}