This series is divided into three parts:
- Set up AWS Cognito and backend Web API user functions - previous post
- Configure CORS in Web API backend - previous post
- Authentication between frontend and Web API backend - this post
We have done our user sign in method that will return an Access Token to the caller (frontend). Now we only want authenticated users access our app. To do this we need to adjust our configurations a little bit.
In our backend Web API, add app.UseAuthentication() in Configure() method in Startup.cs between UseCors() and UseAuthorization():
public void ConfigureServices(IServiceCollection services) { . . . app.UseCors(); app.UseAuthentication(); app.UseAuthorization(); . . . }The order for the middlewares is specify in this ASP.NET Core documentation.
Next, add this line in our existing authentication configurations. We need to disable the default feature that is validating token audience as AWS Access Token does not include 'audience' (aud). So the frontend can present the token to backend without any issues.
public void ConfigureServices(IServiceCollection services) { // AWS Cognito services.AddAuthentication("Bearer") .AddJwtBearer(options => { options.Audience = "[APP_CLIENT_ID]"; options.Authority = "https://cognito-idp.[REGION_NAME].amazonaws.com/[USER_POOL_ID]"; options.TokenValidationParameters = new TokenValidationParameters { ValidateAudience = false }; }); . . . }
To secure any methods, we just need to decorate with [Authorize] attribute. For example:
[Authorize] public IEnumerable<WeatherForecast> Get() { . . . }
Then, in our frontend app, we create sign in functionality that will receive an access token once successful. The token is then stored in local storage that will be used for subsequent requests to the backend.
signin(): void { const params = new HttpParams() .set('username', this.model.Username) .set('password', this.model.Password); var user = this.model; this.http.post<any>('https://localhost:5001/api/signin', {username: this.model.Username, password: this.model.Password}) .subscribe({ next: token => { console.log(token); let atoken = token; localStorage.setItem("atoken", atoken); }, error: error => { console.log(error); } }) }
For further interaction with the backend, we retrieve the token and pass in request header:
getItems(): void { let token = localStorage.getItem("atoken"); this.http.get("https://localhost:5001/weatherforecast", { headers: new HttpHeaders({ "Authorization": "Bearer " + token }) }).subscribe(response => console.log(response)); }
Now we have working frontend and backend that utilise AWS Cognito as authentication provider.