I've a solution in Visual Studio 'TourManagement' which contains 2 projects of .Net core. One is IDP using Identity Server 4, second project is RESTful API of TourManagement secured by IDP project. My question is how can i call Identity Server 4 using Postman to get tokens and call TourManagement Bands API by passing these tokens in header return from identity server in postman? My code is below.
Startup Class in IDP Project
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
namespace Marvin.IDP
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddTestUsers(Config.GetUsers())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryClients(Config.GetClients());
services.AddCors();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors(c => c.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
app.UseIdentityServer();
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}
}
}
Config Class in IDP Project
using IdentityServer4;
using IdentityServer4.Models;
using IdentityServer4.Test;
using System.Collections.Generic;
using System.Security.Claims;
namespace Marvin.IDP
{
public static class Config
{
public static List<TestUser> GetUsers()
{
return new List<TestUser>
{
new TestUser
{
SubjectId = "fec0a4d6-5830-4eb8-8024-272bd5d6d2bb",
Username = "Jon",
Password = "jon123",
Claims = new List<Claim>
{
new Claim("given_name", "Jon"),
new Claim("family_name", "Doe"),
new Claim("role", "Administrator"),
}
},
new TestUser
{
SubjectId = "c3b7f625-c07f-4d7d-9be1-ddff8ff93b4d",
Username = "Steve",
Password = "steve123",
Claims = new List<Claim>
{
new Claim("given_name", "Steve"),
new Claim("family_name", "Smith"),
new Claim("role", "Tour Manager"),
}
}
};
}
public static List<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResource("roles", "Your role(s)", new []{"role"}),
};
}
internal static IEnumerable<ApiResource> GetApiResources()
{
return new[] {
new ApiResource("tourmanagementapi", "Tour Management API", new[] { "role" })
};
}
public static List<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientName = "Tour Management",
ClientId="tourmanagementclient",
AllowedGrantTypes = GrantTypes.Implicit,
RequireConsent = false,
AllowAccessTokensViaBrowser = true,
RedirectUris =new List<string>
{
"https://localhost:4200/signin-oidc",
"https://localhost:4200/redirect-silentrenew"
},
AccessTokenLifetime = 180,
PostLogoutRedirectUris = new[]{
"https://localhost:4200/" },
AllowedScopes = new []
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"roles",
"tourmanagementapi",
}
}
};
}
}
}
Startup Class in TourManagement API Project
using IdentityServer4.AccessTokenValidation;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Linq;
using TourManagement.API.Authorization;
using TourManagement.API.Services;
namespace TourManagement.API
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthorization();
services.AddScoped<IAuthorizationHandler, UserMustBeTourManagerRequirementHandler>();
services.AddMvc(setupAction =>
{
setupAction.ReturnHttpNotAcceptable = true;
})
.AddJsonOptions(options =>
{
options.SerializerSettings.DateParseHandling = DateParseHandling.DateTimeOffset;
options.SerializerSettings.ContractResolver =
new CamelCasePropertyNamesContractResolver();
});
services.AddCors(options =>
{
options.AddPolicy("AllowAllOriginsHeadersAndMethods",
builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
});
var connectionString = Configuration["ConnectionStrings:TourManagementDB"];
services.AddDbContext<TourManagementContext>(o => o.UseSqlServer(connectionString));
services.AddScoped<ITourManagementRepository, TourManagementRepository>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<IUserInfoService, UserInfoService>();
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
options.Authority = "https://localhost:44398";
options.ApiName = "tourmanagementapi";
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler(appBuilder =>
{
appBuilder.Run(async context =>
{
context.Response.StatusCode = 500;
await context.Response.WriteAsync("An unexpected fault happened. Try again later.");
});
});
}
app.UseCors("AllowAllOriginsHeadersAndMethods");
app.UseAuthentication();
app.UseMvc();
}
}
}
Bands Controller in Tourmanagement API Project
using AutoMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
using TourManagement.API.Dtos;
using TourManagement.API.Services;
namespace TourManagement.API.Controllers
{
[Route("api/bands")]
[Authorize]
public class BandsController : Controller
{
private readonly ITourManagementRepository _tourManagementRepository;
public BandsController(ITourManagementRepository tourManagementRepository)
{
_tourManagementRepository = tourManagementRepository;
}
[HttpGet]
public async Task<IActionResult> GetBands()
{
var bandsFromRepo = await _tourManagementRepository.GetBands();
var bands = Mapper.Map<IEnumerable<Band>>(bandsFromRepo);
return Ok(bands);
}
}
}
The key point is getting access token for accessing tourmanagementapi
using implicit flow in Postman for testing .
The first thing is set AllowAccessTokensViaBrowser
to true
in client config in GetClients
function , so that you can transmit access tokens via the browser channel,:
new Client
{
.....
AllowAccessTokensViaBrowser =true,
.....
}
On Postman side , do the following :
In Authorization
Type, there is a dropdownlist, select OAuth2
:
After selecting it, you’ll notice a button that says Get Access Token, click on it and enter the following information (Based on your codes):
Don't enter openid/profile
as Scope since you are using Oauth2 in Postman .
Click on Request Token
, you’ll see a new token added with the name of TokenName
Finally, make sure you add the token to the header then click on Use Token
. Token will available when sending request as authorization header :