Reputation: 98
I am trying to use Identity Server 6 for authentication and authorization in my MVC project in .NET 6. I am also using Identity Server to restrict access to my APIs which talks to my MVC project. When I start my solution, I start all 3 projects under the solutions - Web MVC project with swagger UI, Product API and Identity server API project. When I try to login to my MVC api project , in the console running in the background , I am getting the following error -
Duende.IdentityServer.Events.DefaultEventService[0]
{
"ClientId": "mango",
"Endpoint": "Authorize",
"Scopes": "",
"Error": "invalid_request",
"ErrorDescription": "Invalid redirect_uri",
"Category": "Token",
"Name": "Token Issued Failure",
"EventType": "Failure",
"Id": 2001,
"ActivityId": "0HMH1EO8KTSBE:00000003",
"TimeStamp": "2022-04-18T20:00:33Z",
"ProcessId": 41032,
"LocalIpAddress": "::1:7270",
"RemoteIpAddress": "::1"
}
Here is the code for HomeController of my MVC project -
using Mango.Web.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
namespace Mango.Web.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
[Authorize]
public async Task<IActionResult> Login()
{
return RedirectToAction(nameof(Index));
}
public IActionResult Logout()
{
return SignOut("Cookies", "oidc");
}
}
}
Below is the code for my Program.cs for my MVC project -
using Mango.Web;
using Mango.Web.Services;
using Mango.Web.Services.IServices;
using Microsoft.AspNetCore.Authentication;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddHttpClient<IProductService, ProductService>();
Constants.ProductAPIBase = builder.Configuration["ServiceUrls:ProductAPI"];
builder.Services.AddScoped<IProductService, ProductService>();
//setup main proj to use Identityserver , openID connect
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies", c => c.ExpireTimeSpan = TimeSpan.FromMinutes(10))
.AddOpenIdConnect("oidc", options =>
{
options.Authority = builder.Configuration["ServiceUrls:IdentityAPI"];
options.GetClaimsFromUserInfoEndpoint = true;
options.ClientId = "mango";
options.ClientSecret = "secret";
options.ResponseType = "code";
options.ClaimActions.MapJsonKey("role", "role", "role");
options.ClaimActions.MapJsonKey("sub", "sub", "sub");
options.TokenValidationParameters.NameClaimType = "name";
options.TokenValidationParameters.RoleClaimType = "role";
options.Scope.Add("mango");
options.SaveTokens = true;
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
appsettings.json file for MVC project -
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ServiceUrls": {
"ProductAPI": "https://localhost:7174",
"IdentityAPI": "https://localhost:7270"
}
}
Static class SD.vc in my Identity API project -
namespace Mango.Services.Identity
{
using Duende.IdentityServer;
using Duende.IdentityServer.Models;
public static class SD
{
public const string Admin = "Admin";
public const string Customer = "Customer";
public static IEnumerable<IdentityResource> IdentityResources =>
new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Email(),
new IdentityResources.Profile()
};
public static IEnumerable<ApiScope> ApiScopes =>
new List<ApiScope> {
new ApiScope("mango", "Mango Server"),
new ApiScope(name: "read", displayName: "Read your data."),
new ApiScope(name: "write", displayName: "Write your data."),
new ApiScope(name: "delete", displayName: "Delete your data.")
};
public static IEnumerable<Client> Clients =>
new List<Client>
{
new Client
{
ClientId="client",
ClientSecrets= { new Secret("secret".Sha256())},
AllowedGrantTypes = GrantTypes.ClientCredentials,
AllowedScopes={ "read", "write","profile"}
},
//creating custom client for our mango app
new Client
{
ClientId="mango",
ClientSecrets= { new Secret("secret".Sha256())},
AllowedGrantTypes = GrantTypes.Code,
// for openid connect , we add signin-oidc
//44360 , 7182
RedirectUris={ "https://localhost:44360/signin-oidc", "https://localhost:7182/signin-oidc" },
//url to redirect after logout - main app
PostLogoutRedirectUris={"https://localhost:44360/signout-callback-oidc" },
AllowedScopes=new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"mango"
}
},
};
}
}
Program.cs file for Identity API project -
using Mango.Services.Identity;
using Mango.Services.Identity.DbContext;
using Mango.Services.Identity.Initializer;
using Mango.Services.Identity.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
// configure identityserver to use our App user class
builder.Services.AddIdentity<ApplicationUser,IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders();
//adding identityserver
builder.Services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
options.EmitStaticAudienceClaim = true;
})
//using our resources and apiscopes
.AddInMemoryIdentityResources(SD.IdentityResources)
.AddInMemoryApiScopes(SD.ApiScopes)
.AddInMemoryClients(SD.Clients)
.AddAspNetIdentity<ApplicationUser>();
builder.Services.AddScoped<IDbInitializer, DbInitializer>();
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
//adding identity server to the pipeline
app.UseIdentityServer();
using (var scope = app.Services.CreateScope())
{
scope.ServiceProvider.GetRequiredService<IDbInitializer>().Initialize();
}
//app.Services.GetService<IDbInitializer>().Initialize();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
appsettings.json for Identity API -----
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"DefaultConnection": "Server=Local;Database=MangoIdentityServer;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
I am not sure here what is exactly causing this issue. I have verified my IdentityServer is running on https://localhost:7270/.
Upvotes: 2
Views: 5094
Reputation: 158
You need to add mvc project's url in redirect_uri list of a client in identity server.
Lets say your mvc project url is "https://localhost:9999", add this address in redirect_uri list.
e.g in you identity api, you have a client mango;
new Client
{
ClientId="mango",
ClientSecrets= { new Secret("secret".Sha256())},
AllowedGrantTypes = GrantTypes.Code,
// for openid connect , we add signin-oidc
//44360 , 7182
RedirectUris={ "https://localhost:44360/signin-oidc", "https://localhost:7182/signin-oidc" },
//url to redirect after logout - main app
PostLogoutRedirectUris={"https://localhost:44360/signout-callback-oidc" },
AllowedScopes=new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"mango"
}
},
Change this line
RedirectUris={ "https://localhost:44360/signin-oidc", "https://localhost:7182/signin-oidc" },
to
RedirectUris={ "https://localhost:999/signin-oidc", "https://localhost:44360/signin-oidc", "https://localhost:7182/signin-oidc" },
Added MVC project URL in redirect_uri list.
Your MVC project is sending default value for redirect_uri to identity sever.
Upvotes: 4