Update
I have been able to get a Bearer token using instructions from this thread
Here are the instructions in Postman:
Url: https://login.windows.net/[tenantname].onmicrosoft.com/oauth2/token
Type: POST
Headers: none
Body: form-data
grant_type: client_credentials
client_id: [client-id]
client_secret: [client-secret]
However, if I send the same token in my call to a Web API endpoint, I still get back "Authorization has been denied for this request"
Why is it still not authorizing ?
End Update
I have created an ASP.Net Web API project which is protected using an organizational Azure AD instance. I have set up the tenant id, client id and secret correctly.
The Azure AD instance is the same one backing our Office 365/SharePoint instance and the idea is to create SharePoint Add-Ins which can call the services using the logged in user's context.
I am stuck at testing the API. I can call unauthorized endpoints without any issue. However, when I add the [Authorize] attribute, I always get back this response: "Authorization has been denied for this request."
As I understand it, I need to generate a bearer token and add it to my Postman request in the header (see image). After much Googling, I still have not been able to make this work.
My question is: How do I generate a bearer token for a Web API instance protected by Azure AD.
My configuration code is as below:
public void ConfigureAuth(IAppBuilder app)
{
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
TokenValidationParameters = new TokenValidationParameters {
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"]
},
});
}
First, you can use POSTMAN to test web api protected by the Bearer token. Here's my postman screenshot:
POSTMAN sending bearer token to web api
Basically: in the request header, specify the key as "Authorization", and value as "Bearer [your token". IF you run into errors, look the headers of the response and you'll see more detailed error info.
Note, most tokens have an expiration period, you can try to verify if your token is valid. e.g. https://jwt.io/
Related
Within my Laravel 9 (Jetstream) installation, I've createad an account (admin) and also created an API token for it directly from the user interface available by default. So the API has an account and an API token for it.
I am able to login to my (Laravel) API, using that token as a Bearer token method 'Authorization: Bearer '.
Everything fine for now, I can access protected routes of the API that are only available for logged-in users.
I've implemented this approach within my frontend app (SPA), which is on a different domain.
At a certain point in my frontend app, I need to communicate with my API, so I am doing a request to it using the same approach like I did in Postman. Basically, within my (axios) request, I am configuring the route to the api, and also the required header (Authorization: Bearer xxxx) to authorize the request using the Bearer token.
axios.post(
'url',
{
"body": data
},
{
headers: {
'Authorization': 'Bearer <my token>'
}
}
)
Now, my main problem is that this request (including the token) can be seen in Chrome Developer tools for example (or other request trackings tools)
How can I secure this in a easy and strong way?
For those who know more about Laravel, this way of authorization that comes from Jetrstream is Sanctum, and comes out of the box. I know there's another method of creating tokens, by making an initial request to the API using basic auth, and in response, I'll get a token that I should use for each request. But does that mean that it's more secure? In the end, that "fresh" token will be also visible to next requests, right? Even if it will be deleted on logout. If someone sees that token, he can easily make a request to my API using it and pretend to be a logged in user.
Is JWT a solution?
There must be something that I'm missing here. Any solutions are welcome
We are trying to use auth0 for spring-boot application authentication.
Created Regular Web Application and Machine to Machine Applications in auth0.com and added users under User Management.
Intention is to have a login API to authenticate users and get the access-token after the successful authentication. Use access token (as bearer token) to access other APIs of the spring-boot application.
We provided proper login and callback urls under the Machine To Machine application configuration in auth0.com.
While generating bearer token, apart from client_id, client_secret we have provided grant_type (as client_credentials), audience as https://<>/api/v2 and scope with (openid profile my_scope email roles).
We are getting 401 error while accessing the other APIs using bearer token generated using client_id, client_secret, grant_type and audience.
Wherein, we are getting 403 error while accessing the other APIs using bearer token generated using client_id, client_secret, grant_type, audience and scope.
403 error stack is as below
Client is not authorized to access <<application-domain-in-auth0>>/api/v2/. You need to create a client-grant associated to this API.
We referred to the udemy session (https://www.udemy.com/course/build-secure-apis-with-auth0-and-postman/learn/lecture/12716335#overview)
Any inputs on the overall approach and where we are going wrong.
Thanks
Venkata Madhu
not sure if it can help, but found this more relevant to the problem statement.
https://community.auth0.com/t/how-to-generate-a-management-api-token-automatically/6376
There are a few things you need to do/check:
Create a non-interactive client in Auth0, which will be used to represent your service.
Authorize the non-interactive client to call the Auth0 Management API:
Dashboard > APIs > Auth0 Management API > Non Interactive Clients > Authorize your client
Ensure that the parameters used in the call to /oauth/token are for your non interactive client:
{
grant_type: 'client_credentials',
client_id: 'NON-INTERACTIVE-CLIENT-ID',
client_secret: 'NON-INTERACTIVE-CLIENT-SECRET',
audience: 'https://yourdomain.auth0.com/api/v2/" }
Make sure the access token you receive is passed in the Authorization header for every request made to the Management API. Authorization: Bearer <access_token>
I use an angularJS web application to login to azure => this part is working.
But when I try to access an authorized controller in my web app, I receive the "Authorization has been denied". While the authorization bearer token has been sent to the web API
my Startup.Auth.cs
public void ConfigureAuth(IAppBuilder app)
{
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
ConfigurationManager.AppSettings["ida:Audience"]
},
});
}
ApiController
[Authorize]
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
Error:
<Error>
<script/>
<Message>Authorization has been denied for this request.</Message>
</Error>
Response Header:
VzViQXBwbGljYXRp
b245XGFwaVx2YWx1ZXM=?=
AFAIK, we would leverage adal.js and adal-angular.js in the Angular JS application to authenticate users and get tokens in the client side. Details you could follow the tutorials Azure AD AngularJS getting started and Integrating Azure AD into an AngularJS single page app to narrow this issue.
But when I try to access an authorized controller in my web app, I receive the "Authorization has been denied". While the authorization bearer token has been sent to the web API.
If you manually enable the middleware to validate the token, you need to make sure that you have correctly configured the WindowsAzureActiveDirectoryBearerAuthenticationOptions.Audience or TokenValidationParameters.AllowedAudience(s) which would be compared with the aud property from the incoming JWT token. You could press F12 when browsing your app and trace the Network or use Fiddler to capture your bearer token, then use https://jwt.io/ to decode your token.
Moreover, if you use the built-in Authentication and authorization in Azure App Service for your backend web app, you need to correctly configure the Client ID or ALLOWED TOKEN AUDIENCES for AD authentication under the Authentication / Authorization blade of your app service app.
Anyone here implemented social login through Google for Auth0? I have an issue with the tokens (access and id) being returned after validating with Google.
Here's my code:
var waGoogle = new auth0.WebAuth({
domain: 'testApplication.auth0.com',
clientID: '************',
redirectUri: 'http://localhost:8080/'
})
waGoogle.authorize({
connection: 'google-oauth2',
responseType: 'id_token token'
}, function(err, authResult){
if(err){
console.log('Google Login Error')
console.log(err)
}
});
Google screen shows up, I log in and I am redirected back to my application. From the application, I parse the URL so that I can get the access and id tokens.
let getParameterByName = (name) => {
var match = RegExp('[#&]' + name + '=([^&]*)').exec(window.location.hash);
return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
}
var access_token = getParameterByName('access_token')
var id_token = getParameterByName('id_token')
Issue I am having is that none of the tokens allow me to call my APIs (asp.net web api) which are decorated with the [Authorize] attribute. It returns a:
401 (Unauthorized)
I know that my API is working, as using the normal
Username-Password-Authentication
method where I also obtain an access token, my api calls are just pulling through.
Are there any next steps which I need to do after obtaining the access and id_token from Google? Do I need to make an additional call to Auth0 to obtain the proper access token to be able to call my web api?
Thanks.
The token you are looking for is called an IdP (Identity Provider) Token. This is different from the one issued to you after logging in. There are pretty good instructions on the Auth0 site that walk you through the process of getting that token.
Here is the overview of IdP tokens
Here is a step-by-step guide to calling the Identity Provider
The tl;dr:
To access the IdP token you need to call the Auth0 management API from your server. For that, your server will need a management token. Then use that token to access the endpoint /api/v2/users/[USER_ID]. In the object sent back from Auth0, look for the google identity and extract that token.
Also note, you should probably keep that token on your server if you can. If you can keep those power tokens away from your client your users will be happy.
The server is a .net core API that uses Identity for authentication/authorization and SimpleTokenProvider for generating the JWT tokens. The particular endpoint requires a role authorization.
[Authorize(Roles = "Admin")]
When I get a token from a different controller action method, saves the token in a session and tries to use that token to call the API, or when I hard-code a token gotten from Postman and passes it to the API, the user gets authenticated on the server, but fails to authorize.
The only way the user gets authorized is if I request for the token inside the same controller action method. It also works fine from Postman.
The client code is as below:
string token = "ew0KICAiYWxnIjogIkhTMjU2IiwNCiAg...";
HttpClient client = new HttpClient(handler);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
HttpResponseMessage httpResponse = client.GetAsync("http://localhost:5001/api/dashboard").Result;
if (httpResponse.IsSuccessStatusCode)
{
Console.Write(httpResponse.Content.ReadAsStringAsync().Result);
}
From the server logs, the authorized calls for the same endpoint has the following:
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:5001/api/dashboard
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware:Information: HttpContext.User merged via AutomaticAuthentication from authenticationScheme: Identity.Application.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: Successfully validated the token.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: HttpContext.User merged via AutomaticAuthentication from authenticationScheme: Bearer.
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization was successful for user: xxxxx.
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization was successful for user: xxxxx.
While the unauthorized calls has the following logs:
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:5001/api/dashboard
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: Successfully validated the token.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: HttpContext.User merged via AutomaticAuthentication from authenticationScheme: Bearer.
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization was successful for user: xxxxx.
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed for user: xxxxx.
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.JwtBearer.JwtBearerMiddleware:Information: AuthenticationScheme: Bearer was forbidden.
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware:Information: AuthenticationScheme: Identity.Application was challenged.
I don't know what other option needs to be added to HttpClient for the authorizations to work.
After using wireshark to trace the difference in the requests from HttpClient and Postman, i discovered that .Net Identity sets a Cookie named .AspNetCore.Identity.Application after a user signs in which must be sent as part of the requests for the authorization to work.
After getting the cookie and setting it as part of the subsequent requests, it works fine.