问题
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);
}
}
}
回答1:
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 :
- Enter your api's URL .
In
AuthorizationType, there is a dropdownlist, selectOAuth2: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/profileas Scope since you are using Oauth2 in Postman .Click on
Request Token, you’ll see a new token added with the name ofTokenNameFinally, make sure you add the token to the header then click onUse Token. Token will available when sending request as authorization header :
回答2:
I wrote an entire step by step tutorial on how to make this happen, because the answers to this topic were'nt good enough for me.
What is different to the other responses, is how to get and store the bearer token automatically and use it for testing without having to do anything else. Perfect for integration testing your controller classes.
https://medium.com/@rotter.axel/automatically-sign-in-to-identity-server-4-with-postman-and-test-net-core-controller-methods-bc5d8feb199e
来源:https://stackoverflow.com/questions/58197304/how-to-call-identity-server-4-with-postman-for-login