I'm having issue to call authorize api from react SPA. It's working if removed the [Authorize] attribute in the controller/action, but once added in the attribute, the response goes to SPA home page.
Project Structure
IdentityServer (.net core 3.1 mvc with IdentityServer4 *reference token type)
Login (authentication with IdentityServer and auth callback to Portal)
Portal (.net core 3.1 react SPA, use IdentityServer4.AccessTokenValidation to validate
react
fetch('/api/test').then(async (response) => {
var data = await response.json();
console.dir(response);
console.dir(data);
});
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddControllersWithViews()
.ConfigureApiBehaviorOptions(options => { options.SuppressModelStateInvalidFilter = true; });
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
options.Authority = "https://localhost:44302";
options.ApiName = "api1";
options.ApiSecret = "thisissecret";
});
services.AddSpaStaticFiles(configuration => { configuration.RootPath = "ClientApp/build"; });
}
public override void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); });
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (_WebHostEnvironment.IsDevelopment())
{
spa.UseReactDevelopmentServer("start");
}
});
}
Is worked if the api controller doesn't have the "Authorize" attribute, but once added in then will keep on unauthorized.
Sorry guys, is my mistake that I've missed to set the ApiSecret in IdentityServer. Therefore the it's keep on unauthenticated.
new ApiResource("api1", )
{
// the missing part
ApiSecrets = {
new Secret("thisissecret".Sha256())
}
}
Related
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!
I have created an Asp.Net Web API for google authentication and here is my code in satrtup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = GoogleDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
})
.AddGoogle(options =>
{
options.ClientId = "591241482908-66qgk38nbf1un6xxxxxxxxx.apps.googleusercontent.com";
options.ClientSecret = "GOCSPX-xxxxxxxxxxxxx";
});
services.AddControllers();
}
// 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();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
And there is Login Controller
[Route("api/[controller]")]
[ApiController]
public class LoginController : ControllerBase
{
[HttpGet("{id}")]
[Authorize]
public ActionResult<string> Get(int id)
{
return Ok(this.User);
}
}
Now the code builds successfully, but whenever I run the web API the console and the application shuts down automatically. How Can I solve this?
In an ASP.NET CORE 3.1 Server-Side Blazor app, I am not able to get the AllowAnonymous working for a post type of request web API. The get requests do not have any issues.
Along with the solution for it work, please advise me about the needed security. Perhaps I lowered the security in my trials to get the post request work.
These 3 logs appear for every post request:
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
....
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddDefaultUI()
.AddEntityFrameworkStores<EpisodeContext>();
services.AddMvc(options=> {
options.RespectBrowserAcceptHeader = true; })
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddRazorPages();
services.AddServerSideBlazor().AddCircuitOptions(option => { option.DetailedErrors = true; });
services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<ApplicationUser>>();
services.AddHttpContextAccessor();
services.AddAuthorization(config =>
{
config.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.AddPolicy("RequireAdministratorRole",
policy => policy.RequireRole("admin"));
});
...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
API Controller:
[AllowAnonymous]
[Route("api/[controller]")]
[ApiController]
[Produces("application/json")]
public class DailyContentController : ControllerBase
{
[HttpPost("likeepisode"), AllowAnonymous]
public async Task<bool> LikeEpisode(string episodenumber)
{
bool result = await _CDService.LikeEpisode(episodenumber);
return result;
}
}
Plesk Hosting Settings:
Web Application Firewall
I have been able to stop the unintended redirect by setting the preferred domain to none in the hosting settings:
I created a Blazor WebAssembly proj:
In my Google console I created a new Web application project where I specified
Authorized Javascript Origin and Authorized redirect URIs, like below
In my Blazor proj I added these packages:
Google.Apis.Auth.AspNetCore3
Google.Apis.Drive.v3
My startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddRazorPages();
***services
.AddAuthentication(o =>
{
o.DefaultChallengeScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme;
o.DefaultForbidScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme;
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie()
.AddGoogleOpenIdConnect(options =>
{
options.ClientId = "{--myclientid--}";
options.ClientSecret = {"--myclientsecret--}";
});***
}
and also
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebAssemblyDebugging();
}
else
{
app.UseExceptionHandler("/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.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
***app.UseAuthentication();
app.UseAuthorization();***
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapFallbackToFile("index.html");
});
}
I my WeatherforcastController i added this method:
[HttpGet("DriveFileList")]
[GoogleScopedAuthorize(DriveService.ScopeConstants.DriveReadonly)]
public async Task<List<String>> DriveFileList([FromServices] IGoogleAuthProvider auth)
{
GoogleCredential cred = await auth.GetCredentialAsync();
var service = new DriveService(new BaseClientService.Initializer
{
HttpClientInitializer = cred
});
var files = await service.Files.List().ExecuteAsync();
var fileNames = files.Files.Select(x => x.Name).ToList();
return fileNames;
}
I call above method from my FetchData.razor page like below:
protected override async Task OnInitializedAsync()
{
List<String> myFiles = await Http.GetFromJsonAsync<List<String>>("WeatherForecast/DriveFileList");
}
I run and get a CORS error:
Is there a workaround? Are there other approaches to access the Google Api from Blazor WebAssembly?
Everything works fine and the session keeps it Session Id and data. Then I redirect a user to payment page. After successful payment the user is redirected back to my site
The problem is my sessions lost after redirecting to my application.
How can i fix it?
Thanks
//Redirection code
HttpContext.Response.Redirect(IyziGo.PaymentPageUrl,false);
//Main Configuration
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddRazorRuntimeCompilation();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromHours(4);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = new MyTransparentJsonNamingPolicy();
});
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}
// 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();
}*/
app.UseDeveloperExceptionPage();
app.UseRouting();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=startApp}");
endpoints.MapControllers();
});
}