Using OpenIdConnect with Azure AD, Angular5 and WebAPI Core: Angular5 configuration

 

Install required packages and setup Angular 5 application

Firstly install the latest version of Angular with Angular-CLI

npm install -g @angular/cli

Then install an angular version of ADAL.JS:  adal-angular5

npm install --save adal-angular5

Create a AuthService

We will create a AuthService.ts, this service will manage signin, signout and users data :

auth.service.ts:

import { Adal5HTTPService, Adal5Service } from 'adal-angular5';
import { HttpClient, HttpHandler } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class AuthService {

private_user=null;
private_config = {
   tenant:'136544d9-038e-4646-afff-10accb370679', <-- tenantId mentionned in the previous article
   clientId:'257b6c36-1168-4aac-be93-6f2cd81cec43', <-- clientId mentionned in the previous article
   redirectUri:"http://localhost:4200/auth-callback", <-- callback URI mentionned in the previous article
   postLogoutRedirectUri:"http://localhost:4200" <-- same URI as homepage URI mentionned in the previous article
}

constructor(private_adal:Adal5Service) {
   this._adal.init(this._config);
}

public isLoggedIn():boolean {
   return this._adal.userInfo.authenticated;
}

public signout():void {
   this._adal.logOut();
}

public startAuthentication():any {
   this._adal.login();
}

public getName():string {
   return this._user.profile.name;
}

public completeAuthentication():void {
   this._adal.handleWindowCallback();
   this._adal.getUser().subscribe(user=> {
   this._user=user;
   console.log(this._adal.userInfo);
   var expireIn=user.profile.exp-newDate().getTime();
});

}

}

this service is the most important thing, it will be used everywhere in the application.

Create a AuthGuardService

This AuthGuard service is usefull for protecting your page with authentication

You need to implement CanActivate method using Interface with the same name:

auth-guard.service.ts:

import { AuthService } from './auth.service';
import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';

@Injectable()
export class AuthGuardService implements CanActivate {

constructor(private_authService:AuthService) { }

   canActivate():boolean {

   if(this._authService.isLoggedIn()) {
      return true;
   }
   this._authService.startAuthentication();
    return false;
   }

}

CanActivate is fired when you try to access to a route that is protected.

To setup route protection, create a component served by a protected route you want to protected with authentication, and setup route protection in app.module.ts:

Example of a protected component:

protected.component.ts:

import { AuthService } from './../services/auth.service';
import { Component, OnInit } from '@angular/core';

@Component({
   selector:'app-protected',
   templateUrl:'./protected.component.html',
   styleUrls: ['./protected.component.css']
})

export class ProtectedComponent implements OnInit {

   name:String="";
   constructor(private_authService:AuthService) { }

   ngOnInit() {
      this.name=this._authService.getName();
   }

   public signout():void {
      this._authService.signout();
   }
}

protected.component.html:

<p>

Welcome {{name}}

</p>

<a href="javascript:void(0);" (click)="signout();">signout</a>

Protect your routes like this in app.module.ts:

const routes: Routes = [
{
   path:'',
   children: []
},
{
   path:'protected',
   component:ProtectedComponent,
   canActivate: [AuthGuardService]
},
{
   path:'auth-callback',
   component:AuthCallbackComponent
}
];

Create a AuthCallback component

This component will be used as endpoint in your app to manage user creation after receiving the token from Azure Authorization endpoint.

Azure AD will call your page and send the token. If you remember well, the URI has to be declaqred in Azure to make it work.

auth-callback.component.ts:

import { AuthService } from './../services/auth.service';
import { Router, ActivatedRoute } from '@angular/router';
import { Component, OnInit, NgZone } from '@angular/core';

@Component({
   selector:'app-auth-callback',
   templateUrl:'./auth-callback.component.html',
   styleUrls: ['./auth-callback.component.css']
})

export class AuthCallbackComponent implements OnInit {

   constructor(private_router:Router, private_authService:AuthService, private_zone:NgZone, private_activatedRoute:ActivatedRoute) { }

   ngOnInit() {
      this._authService.completeAuthentication();

      setTimeout(() => {this._zone.run(
      () => this._router.navigate(['/protected'])
      );},200);
   }
}

auth-callback.component.html:

<p>Please wait while we redirect you back</p>

The method completeAuthentication is in fact internally a Promise but I execute the redirection after authentication synchronously by using a setTimeout statement.

I used also NgZone object.

Why this?

Passing a callback to promise after authentication in completeAuthentication did not work on Safari IOS, so the work around was using setTimeout inside NgZone… a bit dirty but it works! 🙂

Modify you app.component.html to test a protected route:

<h3><a routerLink="/">Home</a> | <a routerLink="/protected">Protected</a></h3>
<h1>
{{title}}
</h1>
<router-outlet></router-outlet>

Check your app.module.ts

Your app.module.ts should be well setup like this:

import { AuthService } from './services/auth.service';
import { AuthGuardService } from './services/auth-guard.service';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { ProtectedComponent } from './protected/protected.component';
import { AuthCallbackComponent } from './auth-callback/auth-callback.component';
import { Adal5Service, Adal5HTTPService } from 'adal-angular5';
import { HttpClient } from '@angular/common/http';
const routes: Routes = [
{
   path:'',
   children: []
},
{
   path:'protected',
   component:ProtectedComponent,
   canActivate: [AuthGuardService]
},
{
   path:'auth-callback',
   component:AuthCallbackComponent
}
];

@NgModule({
   declarations: [
      AppComponent,
      ProtectedComponent,
      AuthCallbackComponent
   ],
   imports: [
      BrowserModule,
      RouterModule.forRoot(routes)
   ],
   exports: [RouterModule],
   providers: [AuthGuardService, AuthService, Adal5Service,{ provide:Adal5HTTPService, useFactory:Adal5HTTPService.factory, deps: [HttpClient, Adal5Service] } ],
   bootstrap: [AppComponent]
})

export class AppModule { }

Demo time !!!

If everything is well setup in Azure and in your Angular 5 application, if you try to go to navigate to a protected route you should have a logging page to Microsoft and be redirected to your web application:

 

 

 

 

 

If log in your browser console the authenticated user object you should have something like this :

Awesome right ? 😉

Now let’s see how we protect a Web Api: Using OpenIdConnect with Azure AD, Angular5 and WebAPI Core: WebAPI configuration

Code quality: Using CodeAnalysis.FxCopAnalyzers and Stylecop in .NET Core 2 applications

 

Introduction

Why Code quality is important? Because correctness, maintainability, and even elegance are all involved in creating great code.

Code Quality is a fascinating subject, which comprises a mixture of knowledge, experience, guidelines, principles, patterns and conventions. And if that wasn’t enough, they all should be carefully adapted to each particular team and use case.

The subject gets even more confusing when you start considering tooling. However, choosing the right tools for each team and use case will make achieving quality code simpler.

This article contains an introduction to the Code Quality subject in the .Net Core ecosystem.

CodeAnalysis.FxCopAnalyzers

There are several analyzers available, the most interesting ones in my opinion are:

  • Microsoft.AnalyzerPowerPack
  • Microsoft.CodeAnalysis.FxCopAnalyzers
  • codecracker.CSharp
  • SonarAnalyzer.CSharp
  • StyleCop.Analyzers
  • Microsoft.VisualStudio.Azure.CodeAnalysis (for Azure projects)

In this article I have chosen CodeAnalysis.FxCopAnalyzers.

It can be installed via Nuget Packages, it’s easy to install and it uses a ruleset file, you can download a sample here we will see later how to configure it: myrules.ruleset

Installation

Depending the version Visual Studio you have to be careful with what package version you have to install:

If you don’t install the right package with your current version of Visual Studio you may have issues when you compile your project.

For more information you can referer to the GitHub web page: https://github.com/dotnet/roslyn-analyzers#recommended-version-of-analyzer-packages

In my case I have Visual Studio 2017 15.3 so I have to install the version 2.3.0.

StyleCop.Analyzers

StyleCop is like CodeAnalysis, it uses Roslyn Analyzers but does only care about style programming.

Code analysis searches for patterns which may indicate a bug, while StyleCop is simply enforcing style rules, a simple convention used by your team.

Installation

After installing the Nuget package add in your solution items folder the file stylecop.json (at the same place as your ruleset file), it’s mandatory to add this file to make it work

Then edit your csproj to link your stylecop.json to the project you want to analyze like this (there is no visual tool for this in Visual Studio 2017 for StyleCop):

In the mean time add the ruleset file as follow as well:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>    
     <OutputType>Exe</OutputType>    
     <TargetFramework>netcoreapp2.0</TargetFramework>  
  </PropertyGroup>
  <ItemGroup>  
     <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.3.0-beta1" />    
     <PackageReference Include="StyleCop.Analyzers" Version="1.0.2" />  
  </ItemGroup>    

  <PropertyGroup> 
     <CodeAnalysisRuleSet>$(SolutionDir)\myrules.ruleset</CodeAnalysisRuleSet> 
     <Features>IOperation</Features> 
     <NoWarn></NoWarn>   
  </PropertyGroup>     

  <ItemGroup>    
     <AdditionalFiles Include="$(SolutionDir)\stylecop.json" Link="stylecop.json" />  
  </ItemGroup>  
</Project>

When you are done with that, you can select the rules you want to enable / disable (None, Warning, Error…):

CodeAnalysis rules:

StyleCop rules:

Then when you compile Warnings or Errors appear:

Sample of underlined code:

 

Great isn’t it? 😉

Now your turn to fix analyze your code 😮

Code reliability: Unit testing with XUnit and FluentAssertions in .NET Core 2 apps

Introduction

I decided to write this article because I’m really fan of XUnit and FluentAssertions expecially for its great syntax.

Xunit

xUnit.net is a free, open source, community-focused unit testing tool for the .NET Framework. Written by the original inventor of NUnit v2, xUnit.net is the latest technology for unit testing C#, F#, VB.NET and other .NET languages. xUnit.net works with ReSharper, CodeRush, TestDriven.NET and Xamarin. It is part of the .NET Foundation, and operates under their code of conduct. It is licensed under Apache 2 (an OSI approved license).

FluentAssertions

FluentAssertions is the best assertion framework in the .NET realm.

FluentAssertions supports the following .NET versions:

  • .NET 4.0, 4.5 and 4.6
  • CoreCLR, .NET Native, and Universal Windows Platform
  • Windows Store Apps for Windows 8.1
  • Silverlight 5
  • Windows Phone 8.1
  • Windows Phone Silverlight 8.0 and 8.1
  • Portable Class Libraries

Fluent Assertions supports the following unit test frameworks:

 

Setup your .NET Core 2 project

Install XUnit

Download it via Nuget package manager:

Or type this command in Nuget package manager console:

PM> Install-Package xunit -Version 2.3.1

Install XUnit Visual Studio runner

This package allow to Visual Studio to discover XUnit unit tests, if you don’t install it, Visual Studio won’t detect them.

Download it via Nuget package manager:

Or type this command in Nuget package manager console:

PM> Install-Package xunit.runner.console -Version 2.3.1

Install FluentAssertions

Download it via Nuget package manager:

Or type this command in Nuget package manager console:

PM> Install-Package FluentAssertions -Version 5.0.0-rc0002

 

Write your unit tests

Example of a class to unit test:

public class Hello
{
   private string _firstName { get; set; }
   private string _lastName { get; set; }

   public Hello(string firstName, string lastName)
   {
      _firstName = firstName;
      _lastName = lastName;
   }

   public string HelloMan()
   {
      if (string.IsNullOrEmpty(_firstName))
         throw new MissingFirstNameException();

       return $"Hello {_firstName} {_lastName} !";
   }

   public string Your()
   {
      return $"Hello {_firstName} {_lastName} !";
   }
}

public class MissingFirstNameException: Exception
{
   public MissingFirstNameException(): base("FirstName is missing")
   {
   }
}

Example of a related Unit tests class:

public class HelloTests
{
   [Fact]
   public void HelloManShouldBeWellFormated()
   {
      // Arrange
      var hello = new Hello("John", "Doe");

     //Act
     var helloMan = hello.HelloMan();

     //Assert
     helloMan
     .Should()
     .StartWith("Hello")
     .And
     .EndWith("!")
     .And
     .Contain("John")
     .And
     .Contain("Doe");
   }

   [Fact]
   public void HelloManShouldBeRaiseExceptionWhenFirstNameIsNotSet()
   {
      // Arrange
      var hello = new Hello("", "Doe");

      //Act
      Action actionHelloMan = () => hello.HelloMan();

      //Assert
      actionHelloMan
      .Should()
      .Throw<MissingFirstNameException>()
      .WithMessage("FirstName is missing");
   }
}

 

Now just run your test with “Test” menu in Visual Studio:

 

That’s it!

Cute unit testing isn’t it? 😉