I have Api project and IdentityServer project. User is logged in IdentityServer. How can I get userId of logged user in Api project?
I am authenticated in identity server but I don't have access to api, I see 401 error (unauthorized) when I am trying to call the api method, why?
I have added in Api to Startup.cs in ConfigureServices method:
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
options.Authority = "url to identity server";
options.ApiName = "test";
});
services.AddAuthorization(options =>
{
options.AddPolicy("defaultpolicy", builder =>
{
builder.RequireAuthenticatedUser();
});
});
In Configure method:
app.UseAuthentication();
Api controller:
[Authorize("defaultpolicy")]
public class ApplicationsController : ControllerBase
{
....
}
Inside your [Authorize] protected Api Controller Method you could use:
var userId = User?.FindFirst(ClaimTypes.NameIdentifier);
Related
I configured to use windows authentication for my asp.net react app.
on ConfigureServices() method:
services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate();
services.AddAuthorization(options =>
{
options.FallbackPolicy = options.DefaultPolicy;
});
then on configure() method:
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
However, by doing so, all requests will trigger the authentication process.
I actually only want my api routes (in /api/my/resource ) to be secure using windows authentication, and want to let the whole react resource folder to be public (in /any/path/here).
How do I configure to use windows authentication only for route starting with /api.
I achieved that by just doing this:
services.AddAuthorization(options =>
{
// don't use default policy
// options.FallbackPolicy = options.DefaultPolicy;
});
Then add [Authorize] to the controllers that need authentication.
[Authorize] // trigger authentication process
[Route("api/[controller]")]
[ApiController]
public class MyController : ControllerBase {}
Then I can choose specific routes to require authentication.
I am working on integrating external auth in asp.net core web API project. The frontend is created using create-react-app and backend and frontend are running on different ports on localhost. For auth, I am already using JWT for email/password login. That is working fine. Now I am trying to add external login for Facebook and Google. I have already implemented the same for another asp.net core MVC app using Identity and it's working, because frontend and backend are on the same site.
I am trying to implement the same approach. That is, I call the external login endpoint from react app, it will send redirect response to Facebook, then on successful it will redirect to API, and I will create user if not exist.
The problem is now when on my API send the 302 response, it is giving below error:
Access to XMLHttpRequest at 'https://www.facebook.com/v3.1/dialog/oauth?client_id=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' (redirected from 'https://localhost:44373/api/Auth/external-login?provider=Facebook') from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Here is the code for Startup:
services.AddAuthentication(options => {
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options => {
options.SaveToken = true;
options.RequireHttpsMetadata = true;
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidIssuer = "https://example.com",
ValidAudiences = new string[] { "https://example.com" },
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("keystring"))
};
}).AddFacebook(fbOptions =>
{
fbOptions.AppId = Configuration["FB_APPID"];
fbOptions.AppSecret = Configuration["FB_APPSECRET"];
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddCors(options => options.AddPolicy("AllowAll", p => p.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader().AllowCredentials()));
And the Auth controller:
[AllowAnonymous]
[Route("external-login")]
//[ValidateAntiForgeryToken]
public IActionResult ExternalLogin(string provider, string returnUrl = null)
{
// Request a redirect to the external login provider.
var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "Account", new { returnUrl });
var properties = signinManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return Challenge(properties, provider);
}
I don't want to use Graph API call from asp.net core. Let me know what i am missing.
maybe you need to configure a proxy => https://create-react-app.dev/docs/proxying-api-requests-in-development/
On your API that is running on port 44373 you have to enable CORS to allow request from http://localhost:3000.
Check the next link:
Enable CORS in ASP.NET Core
I need to access to a ASP.net Core API store on Google App Engine from a web page using Google API JS .
For Example :
I've got this script that use Localstorage to store the generated access token
function onSignIn(googleUser) {
var profile = googleUser.getBasicProfile();
var token = googleUser.getAuthResponse().id_token;
LocalStorage.setItem("accessToken", token);
DisplayValues2();
}
function DisplayValues2() {
$.ajax({
url: 'http://localhost:49389/api/values',
method: 'GET',
headers: {
'content-type': 'application/JSON',
'Authorization': 'Bearer ' + localStorage.getItem("accessToken")
},
success: function (data) {
$('#divSuccess').text("");
$('#divSuccess').text(data);
$('#divSuccess').show('fade');
},
error: function (jQXHR) {
if (jQXHR.status == "401") {
$('#errorModal').modal('show');
}
else {
$('#divErrorText').text(jQXHR.responseText);
$('#divError').show('fade');
}
}
});
};
*here the LocalHost:49389 it's just the project that will be push on App Engine
From my http://Localhost:59638/login.html (with the script above) I want to access to the http://localhost:49389/api/values API
My Asp.net Core project is on VS2017 with ASP.Net Core On Google Cloud Platform Web API template.
ValuesController :
[Route("api/[controller]")]
[ApiController]
public class ValuesController : Controller
{
// GET api/values
[HttpGet]
[Authorize]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2", "value3", "value4", "value5" };
}
}
The only thing that change after created the project is the [Authorize] attribute and I receive a :
500 internal server error
And I would like to know,
what should I implement to authenticate the Google token sent in the HTTP header with this API?
Thx
The first thing you will need to do is to ensure that you are telling the authorize to accept a bearer token
[Authorize(AuthenticationSchemes = "Bearer")]
Second is your going to have to make sure that you have the api setup to validate authentication against googles OAuth server.
I am trying to create a call from my Angular 4 application to my server that is asp.net web api, first of all I enabled cors in my server and it seems working, now when I am trying to call I am getting method not allowed
WebApi.config:
public static void Register(HttpConfiguration config)
{
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
Controller method example:
[HttpGet, Route("api/authentication")]
public IHttpActionResult Get(string username, string password)
{
var s = new ApartmentService();
if (!s.CheckIfValidLogin(username, password))
{
return NotFound();
}
return Ok();
}
client code:
public url = 'http://localhost:50743/api/authentication';
login(username: string, password: string): Observable<any> {
let params = new HttpParams();
params.append('username', username);
params.append('password', password);
return this.http.get(this.url, {
params: params,
headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'),
}).map((result: Response) => result.json());
}
i tried also with header content type: application/json and also didn't worked.
error:
its working fine if I did the request with postman...
Thanks.
You are sending a GET request to an endpoint that only accepts POST, that is the reason for the Method Not Allowed error.
Send your request using POST instead. I'm not familiar with angular but try something like
login(username: string, password: string): Observable<any> {
let params = new HttpParams();
params.append('username', username);
params.append('password', password);
return this.http.post(this.url, parems {
headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'),
}).map((result: Response) => result.json());
}
Refer to the angular docs for http.post
I get follow scenario which is working now:
MVC controller using System.Web.Mvc.AuthorizeAttribute to authenticate user is authenticated or not, it will be using cookie.
API controller using System.Web.Http.AuthorizeAttribute to authorise with bearer token.
I do also have angular http interceptor that verify and get bearer token for API purpose that can use among all angular $http request. But I am confusing how to achieve both after user has login?
This is current workflow
User click login, angular verify and store bears token in local storage.
After complete, manually trigger MVC controller so that it will get cookie for MVC authenticate.
This seem to me really double job, or I should focusing on using one AuthorizeAttribute?
You need you use Authorize key to give permission to those functions where authorization is needed. And those functions can only be accessed when authorization token is generated and passed with http request.
module.service('tokenservice', function ($http) {
this.get = function () {
var accesstoken = sessionStorage.getItem('accessToken');
var logged_in = localStorage.getItem('logged_in').toString().trim() === 'false' ? false : true;
var authHeaders = {};
if (accesstoken && logged_in) {
authHeaders.Authorization = 'Bearer ' + accesstoken;
}
return authHeaders;
};
});
module.controller('yourControllerName', function ( $http, tokenservice) {
$http({
method: "POST",
url: '/Controller/MyFucntion',
headers: tokenservice.get(),
});
});
This will help you to get generated token in user login. After that You need to work with your controller
[Authorize]
public JsonResult MyFucntion()
{
//Your logic and calculation
//return
}
Hope that will help