Microsoft Identity Authorize - c#

In my application I'm using Microsoft Identity Authorize to load an AspNet Core view and require the user credentials to access the page.
My problem is that IIS Express executing throug VS 2019, works just fine but when I publish it on IIS (both problem in self-dependent / self-contained) every time that I made a request to access the view it ask me to make the login over and over again.
My Startup.cs file:
namespace SistemaGestor.SOO.Mvc
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<SOOContext>(srv => SOOContextFactory.CreateInstance(Configuration));
//Fernando Milanez 25/09/2019
services.AddTransient<IEmbarcacaoInterface,EmbarcacaoRepositorio>();
services.AddTransient<IBandeiraInterface, BandeiraRepositorio>();
services.AddTransient<IAutenticacao, AutenticacaoRepositorio>();
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie(options =>
{
options.LoginPath = "/Autenticacao/Login";
options.ExpireTimeSpan = TimeSpan.FromMinutes(20);
});
services.AddSession(options =>
{
options.Cookie.IsEssential = true;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddSessionStateTempDataProvider();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
RequestLocalizationOptions localizationOptions = new RequestLocalizationOptions
{
SupportedCultures = new List<CultureInfo> { new CultureInfo("pt-BR") },
SupportedUICultures = new List<CultureInfo> { new CultureInfo("pt-BR") },
DefaultRequestCulture = new RequestCulture("pt-BR")
};
app.UseRequestLocalization(localizationOptions);
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseSession();
app.UseAuthentication(); //Requisito para ativar a autenticao, então é sempre assim adiciono o middlewaree depois defino para usar
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
In my Controller, I've input the [Authorize] attribute:
namespace SistemaGestor.SOO.Mvc
{
[Authorize]
//logical code below
}
I didn't post any error message because it does not show any error.

Related

SSO Authentication - The oauth state was missing or invalid

I am trying to implement SSO Authentication in ASP.Net Core 3.1 and deploy in Pivot Cloud Foundry(PCF).
In local it's working fine but after deployment getting below error
An unhandled exception occurred while processing the request.
Exception: The oauth state was missing or invalid.
Unknown location
Exception: An error was encountered while handling the remote login.
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler.HandleRequestAsync()
HomeController.cs
#if !LOCALTEST
[Authorize]
#endif
public IActionResult Index()
{
string user = "";
if (User.Identity.IsAuthenticated)
{
user = User.Identity.Name;
}
else
{
// WindowsIdentity.GetCurrent
user = WindowsIdentity.GetCurrent().Name.Substring(WindowsIdentity.GetCurrent().Name.LastIndexOf(#"\") + 1);
}
TempData["user"] = user;
return View();
}
Manifest.yml
---
applications:
- name: ApplicationName
memory: 1G
stack: cflinuxfs3
buildpacks:
- dicf_dotnet_core_buildpack_2339_cflinuxfs3
instances: 2
disk_quota: 1G
env:
ASPNETCORE_ENVIRONMENT: Development
GRANT_TYPE: authorization_code
SSO_IDENTITY_PROVIDERS : XXX-sso
SSO_SCOPES : openid,roles,user_attributes
SSO_AUTO_APPROVED_SCOPES : openid,roles,user_attributes
SSO_USERINFO_URL : https://appsso.login.sr3.pcf.xxx.com/userinfo
services :
- serviceName
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddSession();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddMvc();
services.Configure<MyOptions>(myOptions =>
{
myOptions.ConnString = Configuration.GetConnectionString("DefaultConnection");
});
services
.AddMvc()
.AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
services.AddScoped<IRepository, RepositoryConcrete>();
services.AddControllersWithViews();
services.AddRazorPages();
services.AddCloudFoundryContainerIdentity(Configuration);
services.AddAuthentication((options) =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CloudFoundryDefaults.AuthenticationScheme;
})
.AddCookie((options) =>
{
options.AccessDeniedPath = new PathString("/Home/AccessDenied");
})
.AddCloudFoundryOAuth(Configuration);
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddControllersWithViews();
var serviceInfos = CloudFoundryServiceInfoCreator.Instance(Configuration);
var ssoInfo = serviceInfos.GetServiceInfos<SsoServiceInfo>().FirstOrDefault()
?? throw new NullReferenceException("Service info for an SSO Provider was not found!");
userInfoEndPoint = ssoInfo.AuthDomain + "/userinfo";
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
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.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedProto
});
app.UseSession();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
Please help me to know what i am missing or required modification.
Thanking in Advance!

CORS Issue with Dotnet 5 Web Api

I have a dotnet 5 web API with an Angular2+ front end, which I'm building from a previous 3.1 MVC version of the app. I'm having an issue with CORS while looking to authenticate with Yahoo that I did not have with the MVC version. The error I am getting is:
"Access to XMLHttpRequest at 'https://api.login.yahoo.com...' (redirected from 'https://localhost:5003/api/draft/yahooauth/') from origin 'https://localhost:5003' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource."
My API Controller:
[EnableCors("MyPolicy")]
[HttpPost("yahooauth")]
public void YahooAuth()
{
string leftUrl = string.Format("{0}://{1}", HttpContext.Request.Scheme, HttpContext.Request.Host);
string returnUrl = $"{leftUrl}/api/draft/yahooexchange";
string id = configuration["YahooClientId"];
string secret = configuration["YahooClientSecret"];
string url = $"https://api.login.yahoo.com/oauth2/request_auth?client_id={id}&redirect_uri={returnUrl}&response_type=code&language=en-us";
Response.Redirect(url);
}
[HttpGet("yahooexchange/{code}")]
public IActionResult yahooexchange(string code)
{
// Code that is supposed to be triggered with returnUrl from Yahoo
}
Startup.cs:
public class Startup
{
public Startup(IConfiguration configuration) => Configuration = configuration;
public IConfiguration Configuration { get; }
readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential
// cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
// requires using Microsoft.AspNetCore.Http;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddDbContext<IdentityDbCxt>(options => options.UseSqlServer(Configuration.GetConnectionString("IdentityDb")));
services.AddDbContext<DraftContext>(options => options.UseSqlServer(Configuration.GetConnectionString("FSDraftDb")));
services.AddIdentity<AppUser, IdentityRole>(opts =>
{
opts.User.RequireUniqueEmail = true;
})
.AddEntityFrameworkStores<IdentityDbCxt>()
.AddDefaultTokenProviders();
services.AddTransient<IEmailSender, EmailSender>();
services.AddTransient<IAPICall, APICall>();
services.AddTransient<IDraftService, DraftService>();
services.AddCors(options =>
{
options.AddPolicy("MyPolicy",
builder =>
{
builder.WithOrigins("*")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddMvc()
.AddRazorRuntimeCompilation();
services.AddMemoryCache();
services.AddSession();
services.AddSingleton<IHtmlSanitizer, HtmlSanitizer>();
services.AddControllersWithViews(/*options =>
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute())*/);
services.AddRazorPages();
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1",
new OpenApiInfo { Title = "API", Version = "v1" });
});
services
.AddControllers()
.AddNewtonsoftJson();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostEnvironment env, IServiceProvider services)
{
//app.UseMiddleware<GCMiddleware>();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
}
app.UseStatusCodePages();
//app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseSession();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}");
endpoints.MapControllerRoute(
name: "angular_fallback",
pattern: "{target:regex(draft|data|keeper|adminapi|admin`):nonfile}/{*catchall}",
defaults: new { controller = "Home", action = "Index" });
endpoints.MapRazorPages();
});
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "API");
});
app.UseSpa(spa =>
{
string strategy = Configuration.GetValue<string>("DevTools:ConnectionStrategy");
if (strategy == "proxy")
{
spa.UseProxyToSpaDevelopmentServer("http://127.0.0.1:4200");
}
else if (strategy == "managed")
{
spa.Options.SourcePath = "../ClientApp";
spa.UseAngularCliServer("start");
}
});
}
}
I've looked at a few sources, including one quite hopeful post here, but this did not solve my problem: Problems with CORS Response to preflight in dotnet core 3.1
In case it's helpful, I'm looking to do step 2: https://developer.yahoo.com/oauth2/guide/flows_authcode/
Edit: This is the documentation I used regarding CORS: https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-5.0#attr
Try to use this syntax and move AddCors to the top of ConfigureServices. Assign name to UseRouting.
services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
}));
.......
....
app.UseRouting();
app.UseCors("MyPolicy");
app.UseAuthentication();
app.UseAuthorization();
.....
So I ended up figuring out a workaround and just created a new MVC controller, as my previous MVC app worked fine.
In addition, I realized that I had not updated my Yahoo Developer App for the new return URI. This did not fix my CORS problem, but it was preventing this from properly working.
Code from Angular to go to the new controller.
window.location.href = "https://localhost:5003/yahoo/index";
My MVC Controller:
public class YahooController : Controller
{
private IAPICall apiCall;
public YahooController(IAPICall aCall)
{
apiCall = aCall;
}
// getting session data on player values
private DraftService GetDS()
{
DraftService draftService = HttpContext.Session.GetJson<DraftService>("DraftService") ?? new DraftService();
return draftService;
}
// saving session data on player values
private void SaveDS(DraftService ds)
{
HttpContext.Session.SetJson("DraftService", ds);
}
[HttpGet]
public void Index()
{
string returnUrl = Url.Action("yahooexchange",
"yahoo", new
{
},
protocol: HttpContext.Request.Scheme);
string url = apiCall.YahooAuthUrl(returnUrl);
Response.Redirect(url);
}
public void yahooexchange(string code)
{
string content = apiCall.YahooGetToken(code);
var jContent = JsonConvert.DeserializeObject<JObject>(content);
string accessToken = jContent.GetValue("access_token").ToString();
string refreshToken = jContent.GetValue("refresh_token").ToString();
string leftUrl = string.Format("{0}://{1}", HttpContext.Request.Scheme, HttpContext.Request.Host);
DraftService ds = GetDS();
ds.YahooAccessToken = accessToken;
ds.YahooRefreshToken = refreshToken;
SaveDS(ds);
string url = leftUrl + "/draft/" + ds.DraftId;
Response.Redirect(url);
}
}

API call: "Endpoint ... contains authorization metadata, but a middleware was not found that supports authorization."

I am currently working on creating a simple web application in angular using Auth0 to offload the authorization portion. Right now I am trying to connect the front end portion and the backend portion and I am having some trouble.
For some reason when I send a https request to the API it keeps giving me the following error in the chrome console.
So I went to use postman to try and access the api. I got past the CORS part error but instead het Endpoint .... contains authorization metadata, but a middleware was not found that supports authorization.
This is what my startup class looks like in my backend:
public class Startup
{
readonly string MyAllowSpecificOrigins = "localhost_origin";
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
string domain = $"https://{Configuration["Auth0:Domain"]}/";
services.AddControllers();
// 1. Add Authentication Services
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Authority = domain;
options.Audience = Configuration["Auth0:ApiIdentifier"];
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = ClaimTypes.NameIdentifier
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("read:messages", policy => policy.Requirements.Add(new HasScopeRequirement("read:messages", domain)));
});
services.AddSingleton<IAuthorizationHandler, HasScopeHandler>();
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
builder.WithOrigins("https://localhost:4200").AllowAnyMethod().AllowAnyHeader();
});
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors();
app.UseAuthentication();
//app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Here is my test controller that I call the api on:
[Route("api")]
public class TestController : Controller
{
[HttpGet]
[Route("private")]
[Authorize]
public IActionResult Private()
{
return Json(new
{
Message = "Hello from a private endpoint! You need to be authenticated to see this."
});
}
}
I've read the documentation and followed the examples on auth0's sites for implementing this. I can't quite find where I went wrong.
Okay for the people that might run into a similar issue. It ended up being a problem of the order of things in the startup.cs file and making my localhost origin use http instead of https. I wasn't able to deduce this from the tutorial article because they ommitted a lot of code. I ended up having to download the sample project and compare line by line. This is the final startup.cs file that worked for me:
public class Startup
{
readonly string MyAllowSpecificOrigins = "localhost_origin";
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
string domain = $"https://{Configuration["Auth0:Domain"]}/";
services.AddControllers();
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
builder
.WithOrigins("http://localhost:4200")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
// 1. Add Authentication Services
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Authority = domain;
options.Audience = Configuration["Auth0:ApiIdentifier"];
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = ClaimTypes.NameIdentifier
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("read:messages", policy => policy.Requirements.Add(new HasScopeRequirement("read:messages", domain)));
});
services.AddSingleton<IAuthorizationHandler, HasScopeHandler>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}

how to exipre cookies in same session id in asp.net core

What do I miss to clear cookie to logout user .After logout when I click on backward arrow on the browser still my login username and password is saved and I am back to application.Do I need to remove services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
to clear cookie .
Logout Method
/// To logout user from Application
/// </summary>
/// <returns></returns>
[Obsolete]
public IActionResult Logout()
{
var model = new LoginViewModel();
HttpContext.Session.Clear();
HttpContext.Session.Remove(HttpContext.Session.Id);
Response.Cookies.Delete(".AspNetCore.Antiforgery.kLmeyaPL6YU");
foreach (var cookie in Request.Cookies.Keys)
{
Response.Cookies.Delete(cookie);
}
var cookies = Request.Cookies.Keys;
return Redirect("/");
}```
***startup.cs***
``` public void ConfigureServices(IServiceCollection services )
{
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.LoginPath = new PathString("/Account/Login/");
});
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
// var isEmployeeUserPolicy = new AuthorizationPolicyBuilder().RequireRole("Employee").Build();
/* services.AddMvc(options =>
{
options.Filters.Add(new ApplyPolicyOrAuthorizeFilter(isEmployeeUserPolicy));
});*/
// services.AddSignalR();
services.Configure<LdapConfig>(Configuration.GetSection("ldap"));
services.AddScoped<IAuthenticationService, LdapAuthenticationService>();
/* services.AddScoped<ECXSecurityAccess.ECXSecurityAccessClient>(provider => {
var client = new ECXSecurityAccessClient();
// Use configuration object to read it from appconfig.json
client.ClientCredentials.UserName.UserName = Configuration["MyService:Username"];
client.ClientCredentials.UserName.Password = Configuration["MyService:Password"];
client.Endpoint.Address = new EndpointAddress(Configuration["MyService:BaseUrl"]);
return client;
});
services.AddAuthentication(IISDefaults.AuthenticationScheme);
services.Configure<IISOptions>(options => {
options.AutomaticAuthentication = true;
options.ForwardClientCertificate = true;
});*/
services.AddDistributedMemoryCache();
services.AddHttpContextAccessor();
services.AddSession(options =>
{
// Set a short timeout for easy testing.
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.Cookie.HttpOnly = true;
// Make the session cookie essential
options.Cookie.IsEssential = true;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.Configure<MySetting>(Configuration.GetSection("MySetting"));
services.AddSingleton(Configuration);
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.ToPagerList();
var MySetting = Configuration.GetSection("MySetting");
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseCookiePolicy(new CookiePolicyOptions
{
HttpOnly = HttpOnlyPolicy.Always,
Secure = CookieSecurePolicy.Always,
MinimumSameSitePolicy = SameSiteMode.None
});
app.UseAuthentication();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
RequestPath = "/MyImages"
});
app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
RequestPath = "/MyImages"
});
app.UseMiddleware<StackifyMiddleware.RequestTracerMiddleware>();
app.UseCookiePolicy();
app.UseSession();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "Login",
template: "{controller=Account}/{action=Login}/{id?}");
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}```

Identity Server 4 Infinite Loop

I'm working on a asp.net core 2.1 project with identity server 4 installed in it and the users stored in SQL database using entity framework. The Web project has a login page and a dashboard once login is successful.
Please find below the code in Startup.cs,
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
string connectionString = Configuration.GetConnectionString("DefaultConnection");
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddMvc();
services.AddDbContext<ApplicationDbContext>(builder =>
builder.UseSqlServer(connectionString, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly)));
services.AddDbContext<SingleSignOn_dbContext>(builder =>
builder.UseSqlServer(connectionString));
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentityServer(options =>
{
options.UserInteraction.LoginUrl = "/Master/Login"; // Set the default login page for Identity server.
}).AddOperationalStore(options =>
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly)))
.AddConfigurationStore(options =>
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly)))
.AddAspNetIdentity<IdentityUser>()
.AddDeveloperSigningCredential();
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Master/Error");
app.UseHsts();
}
// Only need to run this once.
InitializeDbTestData(app);
app.UseIdentityServer();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Master}/{action=Login}/{id?}");
});
}
Client Details below in IDS:
new Client {
ClientId = "SingleSignOnInternalClient",
ClientName = "Example Implicit Client Application",
AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true,
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"role",
"customAPI.write"
},
AllowedCorsOrigins = new List<string> {"192.168.6.112"},
RedirectUris = new List<string> {"https://localhost:44330/signin-oidc"}, // Configuration.GetSection("TestClient").GetSection("RedirectURL").Value
PostLogoutRedirectUris = new List<string> {"https://localhost:44330"},
RequireConsent = false,
AllowRememberConsent = false,
AccessTokenType = AccessTokenType.Jwt
},
I've created a client project using asp.net core 2.1 and authorize attribute in the contact page (Home controller).
When we clicked on the contact page, it redirects to the Login page of the other project where identity server is installed and when successful user authorization is made. The page is redirected to an infinite loop.
Startup file of client:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
// Use cooking authentication for signing in users.
services.AddAuthentication(options =>
{
options.DefaultScheme = "cookie";
options.DefaultChallengeScheme = "oidc";
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie("cookie")
.AddOpenIdConnect("oidc", options =>
{
options.Authority = Configuration.GetValue<string>("Authority:EndPoint"); //services.Configure<"Authority">(Configuration.GetSection("EndPoint"));
options.ClientId = "SingleSignOnInternalClient";
options.SignInScheme = "cookie";
options.SaveTokens = true;
//options.GetClaimsFromUserInfoEndpoint = true;
options.RequireHttpsMetadata = false;
});
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddMvc(options =>
{
///options.Filters.Add
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
Output Log in Client(infinite redirect Loop):
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 POST http://localhost:44330/signin-oidc application/x-www-form-urlencoded 1473
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: cookie signed in.
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 5.4353ms 302
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:44330/Home/Contact
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Route matched with {action = "Contact", controller = "Home", page = "", area = ""}. Executing controller action with signature Microsoft.AspNetCore.Mvc.IActionResult Contact() on controller IdentityTestClient.Controllers.HomeController (IdentityTestClient).
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes ().
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler:Information: AuthenticationScheme: oidc was challenged.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action IdentityTestClient.Controllers.HomeController.Contact (IdentityTestClient) in 8.3527ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 17.5244ms 302
The Url of the infinite loop is below,
https://localhost:44307/connect/authorize?client_id=SingleSignOnInternalClient&redirect_uri=https%3A%2F%2Flocalhost%3A44330%2Fsignin-oidc&response_type=id_token&scope=openid%20profile&response_mode=form_post&nonce=636969892902312620.YzUzMWRiNTktN2Q5Mi00NzZiLWJhMjQtNzEzMjI5Mzk1MTE2ZjM5NWQ2NTEtOTQ4Yi00MDljLWIyYzQtNWE5OTA3YWZkMDFj&state=CfDJ8HSRls71XI5DkQoP2L7ypNS9cYyKsLJm7m1dhd3hXQldeb3Esa0g7uZHU6MiqjlsqTk6h7QaqxXsFuMk05KZfdVdN2qJ9j9v5zVg-BeAFNT5rH_Suq8NUl47VUSfTl6zyrBLxYYgeLn8gfdaQpbmwsynpBuMZ9FR8C8eoVNxyPyQ0nGdBryxybey4QFO1xnwiENQtddWxPexgDBNsAGFNd5l6IYhdHaunWz9Ab7NHS68xdfwORdsNFMJRHtUxAGGhQ08U1WP_-TD2xm1rctVfUFZ_GqoNyc_KDanEmp4AVo5eEF0KgQl6mx4kH0PRMPHeDh3KjZTddKEVQglT0J2Kjo&x-client-SKU=ID_NETSTANDARD1_4&x-client-ver=5.2.0.0
Both the projects have SSL configured to run https locally.
I'm trying to achieve a single sign on solution which has multiple websites in different domain and using the Identity server for login.
Any inputs will be much appreciated.
services.AddDefaultIdentity<IdentityUser>().AddEntityFrameworkStores<ApplicationDbContext>();
is not needed client side.
Beyond the other things, only your IdP should have access to, it re-configures your auth scheme parameters. Anytime you can compare your configuration with the minimum working one from the official repository.
In my case the issue was that both apps (IS4 and my api) were using http. After logging in (and leaving that session open in the browser) I moved both apps to SSL. Then the loop began.
My solution was deleting all the cookies.

Categories

Resources