In this article, I want to show you an example of how the authentication can be implemented using the ASP.NET Web API as a back-end and Angular 2 as the front-end technology.
For this purpose, I’m going to use an already implemented application and show you just the most important pieces of this.
For this purpose, I’m going to use an already implemented application and show you just the most important pieces of this.
First, let’s take a look at the front-end. In app.module, we will register a new provider who is going to be responsible for providing information about authentication (checking whether the user is logged in or not) and also for performing the authentication. This is an example of the code.
Latest Update In 2017: MBuild Alpha Release .Net Core Tools in Visual Studio 2017- The new release of .Net Core Tools based on MSBuild or .Net Core can be tried in Mac Visual Studio or Visual Studio version 2017 RC or at commandline. These tools can run in both .Net Core 1.1 and 1.0 versions.
- providers: [
- AuthGuard,
- AuthenticationService,
- IdentityService,
- {
- provide: AuthHttp,
- useFactory: getAuthHttp,
- deps: [Http]
- },
First let's take a look at the IdentityService, this is the code for it:
- import { Injectable } from '@angular/core';
- import { Http, Headers, RequestOptions, Response } from '@angular/http';
- import { Observable } from 'rxjs/Observable';
- import 'rxjs/add/operator/map';
- import 'rxjs/add/operator/catch';
- import 'rxjs/add/observable/throw';
- import { AuthHttp } from 'angular2-jwt';
- /**
- * Identity service (to Identity Web API controller).
- */
- @Injectable()
- export class IdentityService {
- headers: Headers;
- options: RequestOptions;
- constructor(private authHttp: AuthHttp, private http: Http) {
- // Creates header for post requests.
- this.headers = new Headers({ 'Content-Type': 'application/json' });
- this.options = new RequestOptions({ headers: this.headers });
- }
- /**
- * Gets all users through AuthHttp.
- */
- public GetAll(): Observable < any > {
- // Sends an authenticated request.
- return this.authHttp.get("/api/identity/GetAll")
- .map((res: Response) => {
- return res.json();
- })
- .catch((error: any) => {
- // Error on get request.
- return Observable.throw(error);
- });
- }
- /**
- * Creates a new user.
- *
- * @param model User's data
- * @return An IdentityResult
- */
- public Create(model: any): Observable < any > {
- let body: string = JSON.stringify(model);
- return this.http.post("/api/identity/Create", body, this.options)
- .map((res: Response) => {
- return res.json();
- })
- .catch((error: any) => {
- // Error on post request.
- return Observable.throw(error);
- });
- }
- /**
- * Deletes a user through AuthHttp.
- *
- * @param username Username of the user
- * @return An IdentityResult
- */
- public Delete(username: string): Observable < any > {
- let body: string = JSON.stringify(username);
- // Sends an authenticated request.
- return this.authHttp.post("/api/identity/Delete", body, this.options)
- .map((res: Response) => {
- return res.json();
- })
- .catch((error: any) => {
- // Error on post request.
- return Observable.throw(error);
- });
- }
- // Add other methods.
- }
Here, we have functions that allow us to Create, Delete, and Get All users of the current application. Please note that for this purpose, we are using the http get/post methods pointing to the URI (Unique Resource Identifier) of API.
Read more at Parameterized URL Routing in Asp.Net MVC Application.
Now, let's take a look at the Authentication Service.
- import { Injectable } from '@angular/core';
- import { Http, Headers, RequestOptions, Response } from '@angular/http';
- import { Observable } from 'rxjs/Observable';
- import 'rxjs/add/operator/map';
- import 'rxjs/add/operator/catch';
- import 'rxjs/add/observable/throw';
- import { JwtHelper, tokenNotExpired } from 'angular2-jwt';
- import { Config } from '../config';
- /**
- * ROPC Authentication service.
- */
- @Injectable() export class AuthenticationService {
- /**
- * Stores the URL so we can redirect after signing in.
- */
- public redirectUrl: string;
- /**
- * User's data.
- */
- private user: any = {};
- private headers: Headers;
- private options: RequestOptions;
- constructor(private http: Http) {
- // On bootstrap or refresh tries to get the user's data.
- this.decodeToken();
- // Creates header for post requests.
- this.headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
- this.options = new RequestOptions({ headers: this.headers });
- }
- /**
- * Tries to sign in the user.
- *
- * @param username
- * @param password
- * @return The user's data
- */
- public signin(username: string, password: string): Observable<any> {
- // Token endpoint & params.
- let tokenEndpoint: string = Config.TOKEN_ENDPOINT;
- let params: any = {
- client_id: Config.CLIENT_ID,
- grant_type: Config.GRANT_TYPE,
- username: username,
- password: password,
- scope: Config.SCOPE
- };
- // Encodes the parameters.
- let body: string = this.encodeParams(params);
- return this.http.post(tokenEndpoint, body, this.options)
- .map((res: Response) => {
- let body: any = res.json();
- // Sign in successfully if there's an access token in the response.
- if (typeof body.access_token !== 'undefined') {
- // Stores access token & refresh token.
- this.store(body);
- }
- }).catch((error: any) => {
- // Error on post request.
- return Observable.throw(error);
- });
- }
- /**
- * Tries to get a new token using refresh token.
- */
- public getNewToken(): void {
- let refreshToken: string = localStorage.getItem('refresh_token');
- if (refreshToken != null) {
- // Token endpoint & params.
- let tokenEndpoint: string = Config.TOKEN_ENDPOINT;
- let params: any = {
- client_id: Config.CLIENT_ID,
- grant_type: "refresh_token",
- refresh_token: refreshToken
- };
- // Encodes the parameters.
- let body: string = this.encodeParams(params);
- this.http.post(tokenEndpoint, body, this.options)
- .subscribe(
- (res: Response) => {
- let body: any = res.json();
- // Successful if there's an access token in the response.
- if (typeof body.access_token !== 'undefined') {
- // Stores access token & refresh token.
- this.store(body);
- }
- });
- }
- }
- /**
- * Revokes token.
- */
- public revokeToken(): void {
- let token: string = localStorage.getItem('id_token');
- if (token != null) {
- // Revocation endpoint & params.
- let revocationEndpoint: string = Config.REVOCATION_ENDPOINT;
- let params: any = {
- client_id: Config.CLIENT_ID,
- token_type_hint: "access_token",
- token: token
- };
- // Encodes the parameters.
- let body: string = this.encodeParams(params);
- this.http.post(revocationEndpoint, body, this.options)
- .subscribe(
- () => {
- localStorage.removeItem('id_token');
- });
- }
- }
- /**
- * Revokes refresh token.
- */
- public revokeRefreshToken(): void {
- let refreshToken: string = localStorage.getItem('refresh_token');
- if (refreshToken != null) {
- // Revocation endpoint & params.
- let revocationEndpoint: string = Config.REVOCATION_ENDPOINT;
- let params: any = {
- client_id: Config.CLIENT_ID,
- token_type_hint: "refresh_token",
- token: refreshToken
- };
- // Encodes the parameters.
- let body: string = this.encodeParams(params);
- this.http.post(revocationEndpoint, body, this.options)
- .subscribe(
- () => {
- localStorage.removeItem('refresh_token');
- });
- }
- }
- /**
- * Removes user and revokes tokens.
- */
- public signout(): void {
- this.redirectUrl = null;
- this.user = {};
- // Revokes token.
- this.revokeToken();
- // Revokes refresh token.
- this.revokeRefreshToken();
- }
- /**
- * Gets user's data.
- *
- * @return The user's data
- */
- public getUser(): any {
- return this.user;
- }
- /**
- * Decodes token through JwtHelper.
- */
- private decodeToken(): void {
- if (tokenNotExpired()) {
- let token: string = localStorage.getItem('id_token');
- let jwtHelper: JwtHelper = new JwtHelper();
- this.user = jwtHelper.decodeToken(token);
- }
- }
- /**
- * // Encodes the parameters.
- *
- * @param params The parameters to be encoded
- * @return The encoded parameters
- */
- private encodeParams(params: any): string {
- let body: string = "";
- for (let key in params) {
- if (body.length) {
- body += "&";
- }
- body += key + "=";
- body += encodeURIComponent(params[key]);
- }
- return body;
- }
- /**
- * Stores access token & refresh token.
- *
- * @param body The response of the request to the token endpoint
- */
- private store(body: any): void {
- // Stores access token in local storage to keep user signed in.
- localStorage.setItem('id_token', body.access_token);
- // Stores refresh token in local storage.
- localStorage.setItem('refresh_token', body.refresh_token);
- // Decodes the token.
- this.decodeToken();
- }
- }
Here, we can note the usage of JWT (JavaScript Web Token); this service is responsible for performing the login/logout functionalities, and also for managing the life cycle of the logged-in user object.
The method getUser() retrieves a user which is currently logged in, in order to be able to access the information of that user.
Now, let’s take a look at the AuthGuard.
The method getUser() retrieves a user which is currently logged in, in order to be able to access the information of that user.
Now, let’s take a look at the AuthGuard.
- import { Injectable } from '@angular/core';
- import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
- import { tokenNotExpired } from 'angular2-jwt';
- import { AuthenticationService } from './authentication.service';
- /**
- * Decides if a route can be activated.
- */
- @Injectable() export class AuthGuard implements CanActivate {
- constructor(public authenticationService: AuthenticationService, private router: Router) { }
- public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
- if (tokenNotExpired()) {
- // Signed in.
- return true;
- }
- // Stores the attempted URL for redirecting.
- let url: string = state.url;
- this.authenticationService.redirectUrl = url;
- // Not signed in so redirects to signin page.
- this.router.navigate(['/signin']);
- return false;
- }
- }
This guard performs validation, to see whether the user is logged in or not. Guards are normally used and associated with routes of the Angular2 application, to check whether the user can access the route or not, and in our case, the condition to pass the guard is that the user should be logged in.
Also, this guard redirects a user to the login component if the user is currently not logged in.
Here is an example of how we can apply the guard to some specific routes.
Also, this guard redirects a user to the login component if the user is currently not logged in.
Here is an example of how we can apply the guard to some specific routes.
- Routes = [
- { path: '', redirectTo: 'home', pathMatch: 'full' },
- { path: 'home', component: HomeComponent },
- { path: 'resources', component: ResourcesComponent, canActivate: [AuthGuard] },
- { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] },
- { path: 'signin', component: SigninComponent },
- { path: 'signup', component: SignupComponent }
- ];
- # So the main idea here is to separate public routes from ones that require the user to be logged in.
- Now let’s take a look at the asp.net web api example:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- using Microsoft.AspNetCore.Http;
- using Microsoft.AspNetCore.Mvc;
- using Microsoft.AspNetCore.Authorization;
- using ******.DataCore.Models;
- using Microsoft.AspNetCore.Identity;
- using ******.ApiCore.Services;
- using ******.DataCore.Access;
- using Microsoft.Extensions.Logging;
- using System.Security.Claims;
- using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
- using IdentityModel;
- using ******.ApiCore.Models.AccountViewModels;
- using IdentityServer4.Extensions;
- using Microsoft.EntityFrameworkCore;
- namespace ******.ApiCore.Controllers
- {
- /// <summary>
- /// Identity Web API controller.
- /// </summary>
- [Route("api/[controller]")]
- //[Authorize(Policy = "Manage Accounts")] // Authorization policy for this API.
- public class IdentityController : ControllerBase
- {
- private readonly UserManager<ApplicationUser> _userManager;
- private readonly SignInManager<ApplicationUser> _signInManager;
- private readonly IEmailSender _emailSender;
- private readonly ISmsSender _smsSender;
- private readonly ILogger _logger;
- private readonly ApplicationDbContext _context;
- public IdentityController(
- UserManager<ApplicationUser> userManager,
- SignInManager<ApplicationUser> signInManager,
- IEmailSender emailSender,
- ISmsSender smsSender,
- ILoggerFactory loggerFactory,
- ApplicationDbContext context)
- {
- _userManager = userManager;
- _signInManager = signInManager;
- _emailSender = emailSender;
- _smsSender = smsSender;
- _logger = loggerFactory.CreateLogger<IdentityController>();
- _context = context;
- }
- [HttpGet]
- [AllowAnonymous]
- public void Get()
- {
- var sports = _context.Sports.Include(x => x.Associations);
- var sport = _context.Associations;
- }
- /// <summary>
- /// Gets all the users (user role).
- /// </summary>
- /// <returns>Returns all the users</returns>
- // GET api/identity/getall
- [HttpGet("GetAll")]
- public async Task<IActionResult> GetAll()
- {
- var claim = new Claim("role", "user");
- var users = await _userManager.GetUsersForClaimAsync(claim);
- return new JsonResult(users);
- }
- /// <summary>
- /// Registers a new user.
- /// </summary>
- /// <returns>IdentityResult</returns>
- // POST: api/identity/register
- [HttpPost]
- [AllowAnonymous]
- public async Task<IActionResult> Register([FromBody]RegisterViewModel model)
- {
- var user = new ApplicationUser
- {
- UserName = model.Username,
- Email = model.Email
- };
- var claims = new IdentityUserClaim<string>[]
- {
- new IdentityUserClaim<string> { ClaimType = JwtClaimTypes.PreferredUserName, ClaimValue = model.Username },
- new IdentityUserClaim<string> { ClaimType = JwtClaimTypes.Email, ClaimValue = model.Email },
- new IdentityUserClaim<string> { ClaimType = JwtClaimTypes.Role, ClaimValue = "user" }
- };
- foreach (var claim in claims)
- {
- user.Claims.Add(claim);
- }
- var result = await _userManager.CreateAsync(user, model.Password);
- // Option: enable account confirmation and password reset.
- return new JsonResult(result);
- }
- /// <summary>
- /// Deletes a user.
- /// </summary>
- /// <returns>IdentityResult</returns>
- // POST: api/identity/delete
- [HttpPost("delete")]
- public async Task<IActionResult> Delete([FromBody]string username)
- {
- var user = await _userManager.FindByNameAsync(username);
- var result = await _userManager.DeleteAsync(user);
- return new JsonResult(result);
- }
- // Add other methods.
- }
- }
Here, you have the mapping of paths and methods from identityService. I’m using the standard authentication from .NET, based on .NET identity.
The very same could be done for the sign in and sign out. We just need to generate and store JWT in our front-end Angular 2 application, and then use the stored token to make sure if the user is logged in or not.
You must try this guide. If you face any issue while implementing authentication with Angular 2 apps and ASP.NET Web API, ask me in the comments. Your feedback is valuable, so share your thoughts regarding this post.
The very same could be done for the sign in and sign out. We just need to generate and store JWT in our front-end Angular 2 application, and then use the stored token to make sure if the user is logged in or not.
You must try this guide. If you face any issue while implementing authentication with Angular 2 apps and ASP.NET Web API, ask me in the comments. Your feedback is valuable, so share your thoughts regarding this post.

Ariberto MoraesPosted Nov 19, 2022, 5:16 PM
I found this material very good . Hello Larry, would you ask me to send the LINK of this Code, because I'm learning and I'm interested.
Mohd SalauddinPosted Apr 26, 2019, 8:03 AM
Hi sir very good explanations of each topics..but please add some information where you are adding all these codes in which files..
Tiago GereviniPosted Apr 8, 2019, 4:10 PM
Could you please send me the code?
Hamid KhanPosted Jan 30, 2019, 1:29 AM
Good example..................
budhimanta garnayakPosted Jan 21, 2018, 6:16 AM
Could you please provide complete code
Juan FernándezPosted Oct 29, 2017, 7:32 AM
Please can you share the code?
Tae KwonPosted Oct 17, 2017, 7:46 PM
Hi johnny can you share the code for this
karthikeyan jPosted Oct 13, 2017, 8:35 AM
Hi Johnny, can you share the code for this....My Mail id : [email protected]
Navneet KumarPosted Aug 23, 2017, 3:50 AM
Hi Johnny can you share the code for this....
Faisal AyubPosted Aug 21, 2017, 7:07 AM
Sir can you plz send me this configure project?
abhishek tannaPosted Aug 12, 2017, 3:25 AM
"import { Config } from '../config'; "..please provide code for ../Config..??
Binh TuanPosted Aug 7, 2017, 10:05 PM
Can you pls share the source code link
shiv shankarPosted Jun 23, 2017, 3:17 AM
Can you pls share the source code link
Annette FindleyPosted Feb 13, 2017, 11:16 AM
Thanks. What is in your config that you are referencing?
Humayun Kabir MamunPosted Jan 3, 2017, 6:27 AM
Nice article about Angular2 & Web API...
Jaco ZwartsPosted Jan 3, 2017, 5:52 AM
Thank you for sharing this
Fabio Silva LimaPosted Dec 27, 2016, 1:34 PM
Welcome Johnny! Thanks for sharing