I'm building a SPA application that uses my API through the OAuth Authentication mechanism. My application doesn't has a login view, so I get a token by writing the username and password in the code same, in this way:
$.ajax({
type: "POST",
url: restServer + "/token",
dataType: 'json',
// insecure :
data: {
grant_type : 'password',
scope : '*',
username : 'someuser',
password : 'p4sSw0rd'
}
})
//...
but obviously it is an insecure way to do this, everyone can read the username and the password.
I tried to find about this problem on stackoverflow, etc. but I don't understand how I can solve it.
someone says to get the user and password from the server, but it has the same security problem.
someone mentions https, but in this first step it is not involved.
someone has ideas?
You should not keep usernames and passwords around in your JavaScript code. They are too easy to be stolen.
SPA application are supposed to use the implicit grant in OAuth 2.0. That means on log in you redirect the client to the authorization server to authenticate. The authorization server will redirect the client back to your SPA after authentication and authorization completed. The resulting access token (JWT token) can be used to make calls to your REST API in the backend.
When the access token expires, you communicate with the authorization server to get a new token. User interaction may be required for this.
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>
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.
Well, since the Other problem(solved) remain unsolved, I was thinking to use POSTMan to do Trial and Error on each steps that the Client library will do.
So I read the Basic steps of Google OAuth2 again, created another OAuth 2 ID at Api Manager > Credentials in Dev Console and ID type is Web Application, and filled them into the POSTMan:
New tab in POSTMan, then click the Authorization label.
Choose type as OAuth 2.0 and select "Add token to the url"
Auth URL: https://accounts.google.com/o/oauth2/v2/auth
Access Token URL: https://www.googleapis.com/oauth2/v4/token
Client ID: [the Client ID that I just received]
Client Secret: [the Client secret that I just received]
Scope: [empty]
Grant Type: Authorization Code
Request access token locally: Selected
Click "Request Token"
POSTMan replied me: "Could not complete OAuth2.0 login"
Do I missed something?
(Google redirect URI could be found here)
(API scope could be found here)
You get access Token only when a Google User Logs in through the google signin page.
Step 1:
Redirect
https://accounts.google.com/o/oauth2/auth?client_id=" + GoogleClientID + "&redirect_uri=" + Url.Encode(GoogleRedirectURL) + "&response_type=code&scope=email"
Step 2:
Now you are on google signin page and you would enter your google credentials.
Step 3 :
Google will redirect you back to the redirect_uri that you have configured in the Google Developer Console and you can get the "code" from the QueryString
Step 4:
Now you post a form to https://www.googleapis.com/oauth2/v4/token
with client_id, client_secret, redirect_uri, code(you obtained in Step 3), and the grant_type=authorization_code
Result: You should now receive the access_token from Google
BigHomie's suggestion of scope to 'email' worked for me as well.
But I used a different Auth URL and Access Token URL than BigHomie, because I think it's been updated.
Auth URL:
https://accounts.google.com/o/oauth2/auth
Access Token URL:
https://accounts.google.com/o/oauth2/token
I followed Rajat's instructions, and they worked but afterward I tried what the OP did again but this time setting the scope to 'email' instead of leaving it blank, I got a prompt to enter my gmail creds, and was able to get access token.
How to authorize only my app to use my REST API ?
I have this code in Javascript
$.ajax({
type: 'DELETE',
url : 'removeTest',
data: { ... },
beforeSend:function(){
...
},
complete:function(){
...
},
success:function(data, textStatus, jqXHR){
...
}
});
This call will remove a user from the database with REST API in PHP. The problem is that everyone can remove a user, with POSTMAN (Chrome plugin) for exemple. How can I protect my REST API to authorize only my app.
Check the HTTP_REFERER is not enough. What could be better ?
Thanks for your help
You have several possibilities here. In general you could authorize the user, the app or both. This depends on your application requirements.
Authenticate Applications
To authenticate the application you could use a token based system, such as an API-Key. This means any request would be signed using additional request parameters. Take a look at the way amazon does this in their S3 service for example. If your application will be the only one that will access the rest API you could alternatively simply restrict the acces by the IP address.
If there will be multiple users using the service via your client, you may also need to authorize the access to certain functions. For example: Will every user be allowed to delete any resource? If the answer is no, you have to implement
Authenticate and authorize users
A simple way to authenticate users in a RESTful API is using HTTP Basic or Digest Auth. In this setting the user credentials are sent via the Authorization header in a form of username:password as Base64 encoded hash to the server. Please note that you should only do this via an secured connection using HTTPS!
Additionally you could also take a look at more complex/sophisticated practices like OAuth.