Skip to content

Instantly share code, notes, and snippets.

@RafPe
Last active April 13, 2018 02:31
Show Gist options
  • Save RafPe/661fe84b9c309f2014e8fb4946feb770 to your computer and use it in GitHub Desktop.
Save RafPe/661fe84b9c309f2014e8fb4946feb770 to your computer and use it in GitHub Desktop.
.Net core startup with JWT from AWS cognito
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
using System.Security.Cryptography;
using Microsoft.AspNetCore.Identity;
namespace aspnetcore.webapi_jtw_aws
{
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthorization(auth =>
{
auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme‌​)
.RequireAuthenticatedUser()
.Build());
});
// Add framework services.
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseJwtBearerAuthentication(new JwtBearerOptions()
{
TokenValidationParameters = this.TokenValidationParameters("issuer")
});
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseMvc();
}
// We need to dispose the object to avoid memory leak ;)
// check comments on blog for details
public RsaSecurityKey SigningKey(string key, string expo)
{
using (RSA rsa = RSA.Create())
{
rsa.ImportParameters(
new RSAParameters
{
Modulus = Base64UrlEncoder.DecodeBytes(key),
Exponent = Base64UrlEncoder.DecodeBytes(expo)
}
);
return new RsaSecurityKey(rsa);
}
}
public TokenValidationParameters TokenValidationParameters(string issuer)
{
// Basic settings - signing key to validate with, audience and issuer.
return new TokenValidationParameters
{
// Basic settings - signing key to validate with, IssuerSigningKey and issuer.
IssuerSigningKey = this.SigningKey("key","expo"),
ValidIssuer = issuer,
// when receiving a token, check that the signing key
ValidateIssuerSigningKey = true,
// When receiving a token, check that we've signed it.
ValidateIssuer = true,
// When receiving a token, check that it is still valid.
ValidateLifetime = true,
// Do not validate Audience on the "access" token since Cognito does not supply it but it is on the "id"
ValidateAudience = false,
// This defines the maximum allowable clock skew - i.e. provides a tolerance on the token expiry time
// when validating the lifetime. As we're creating the tokens locally and validating them on the same
// machines which should have synchronised time, this can be set to zero. Where external tokens are
// used, some leeway here could be useful.
ClockSkew = TimeSpan.FromMinutes(0)
};
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment