I'm trying to do an Api Call, this is the code I'm using
axios.get("url", userData, {
headers: {
Authorization: "test"
}
}).then((response) => console.log(response, 'users/me'))
.catch(err => console.log(err))
Its showing me the same error everytime
401 (Unauthorized)
And on the network on chrome dev tools, the Authorization is not appearing at all
Thanks a lot.
The Authorization reqest header has the following general scheme:
Authorization: <auth-scheme> <authorization-parameters>
Let us assume that your user id is john.smith and your password is password (don't do that).
Using the Basic authorization scheme, you take your user ID and password and join them with a colon:
john.smith:password
and then base-64 encyrpt that to get
am9obi5zbWl0aDpwYXNzd29yZA==
The Authorization header you need to pass then is
Authorization: Basic am9obi5zbWl0aDpwYXNzd29yZA==
Different schemes, of course, require different things in the header value.
Your 401 Unauthorized response status should have a WWW-Authenticate response header containing a list of 1 or more challenges telling you what authentication scheme(s) you may use.
Install Postman and fiddle with your API call until you get it working.
You can then export the API call as any of a number of different flavors of client-side code, Node.js - Axios being one of them.
Related
I'm trying to get an access token from Azure. I was following this tutorial, but the thing is that the guy's using postman. It works for me in postman as well, but it fails in javascript and I don't understand why.
function getAccessToken() {
fetch(`${loginUrl}${tenantId}/oauth2/token`, {
method: "POST",
body: JSON.stringify({
grant_type: "client_credentials",
client_id: clientId,
client_secret: clientSecret,
resource: resource,
})
})
.then((response) => {
console.log(JSON.stringify(response));
})
.catch((err) => {
console.log(JSON.stringify(err));
});
}
The credentials are good, i.e. the clientId, secret, tenantid etc.
I also tried in PowerShell and it worked:
Invoke-RestMethod `
-Uri "$loginUrl$tenantId/oauth2/token" `
-Method Post `
-Body #{"grant_type"="client_credentials"; "resource" = $resource; "client_id" = $clientId; "client_secret" = $clientSecret }
But on js I get the following error:
Access to fetch at 'https://login.microsoftonline.com/myTenantId/oauth2/token' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I'm running this script in an HTML file for testing purposes at the moment.
If we directly call the rest api from a domain different from your website in the HTML page, we will get CORS issue. This is for safety reasons. For more details, please refer to here.
So if you want to get Azure AD token in HTML page, I suggest you use package msaljs to implement implicit flow to get token. The package has fixed cors issue. Regarding how to do that, please refer to here.
Besides, if you still want to use client credentials flow to get token in your HTML page. You have two choices. One choice is to use proxy server. The proxy acts as an intermediary between a client and server. For future details about it, please refer to the blog.
I'm trying to do some basic authorisation to my the endpoints in an express app using express-basic-auth, but it keeps giving me a 401 unauthorised. I think the headers I'm sending in Post man are incorrect:
Middleware:
app.use(basicAuth({
users: {'admin': 'supersecret'},
unauthorizedResponse: 'You are not authorized.'
}));
Postman GET request headers:
Authorization:admin:supersecret
How can I get authorised based on the headers?
Your authorization header should look like this: Authorization: Basic YWRtaW46c3VwZXJzZWNyZXQ=
The last part is the result of encoding admin:supersecret. I just found this tool to generate basic authentication headers, however, Postman can generate the headers itself. Just click on the Authorization option next to Headers and choose Basic Auth.
I'm using React Native with the plugin for the Universal Windows Platform to access remote resources on a REST server.
When doing a fetch request for a resource that requires authorization via HTTP Basic Auth, I can provide the request with an additional "Authorization" header and everything works fine as long as the credentials are correct.
If the credentials are wrong I'm presented with a Windows-native login prompt (similar to the one when connecting to a remote computer). This prompt is not managed by my app, but automatically seems to pop up when the underlying network connection detects a 401 Unauthorized server response.
Here is what I do inside React Native:
let encodedCredentials = new Buffer(this.state.username + ":" + this.state.password).toString("base64");
let response = await fetch(this.state.serverUrl, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': "Basic " + encodedCredentials,
}
});
let responseJson = await response.text();
alert(responseJson);
The server response, when provided with incorrect credentials, includes:
Status Code: 401 Unauthorized
WWW-Authenticate: Basic realm="iOSResource"
Note that the native login prompt seems to delay the fetch request as a whole. I can enter wrong credentials and confirm the prompt multiple times without the alert firing once. Only when the prompt is explicitly cancelled, the correct credentials are entered or wrong credentials have been tried a couple of times the fetch await continues.
Unfortunately this brings up another issue: When entering wrong credentials in the popup prompt a couple of times and it finally "gives up", I can supply whatever credentials I want to the fetch request, it will not supply my own authorization header to the server in any future requests. The data sent will be stuck to whatever I entered in the prompt before it closed. In this case it does not bring up the prompt again and the request just immediately fails. That leaves me unable to correct the credentials in my own app, because they are simply not sent within the request. I have confirmed this by inspecting the outgoing data in Wireshark.
I guess Windows seems to transparently tamper with the network request to intercept special response codes and re-prompt credentials if necessary before returning the request result to the actual caller for the first time.
I want to deal with incorrect credentials in the app, instead of causing Windows to intercept requests. Is there a way to suppress this native prompt and immediately proceed with my own code in case the Basic Auth fails?
Edit: The behavior is exactly the same when using Axios instead of plain fetch. Seems like both ultimately do a XMLHttpRequest, which is filtered the same way.
I'm using create-react-app and trying to figure out what I'm doing wrong here.
I created an integration test in mocha using supertest which works fine:
it.only('Can get a list of users', async () => {
const uri = '/users'
console.log(uri)
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0OTk0NDM5NDM5MjMsImV4cCI6MTUwMjAzNTk0MzkyMywidXNlclVVSUQiOiI1YjMyMTQ4MC00ZmY1LTExZTctYWMwNi1kNWNmZmY0NmZjOGMiLCJjc3JBZG1pbiI6dHJ1ZSwiY29nbml0b1VzZXJBcm4iOiJ1cy13ZXN0LTI6NGZjMGFlMDgtNjZhNy00ZDUwLTk2ZDAtOWE3ZmQ0ODAzMWUwIiwicHJvZmlsZXMiOlt7InByb2ZpbGVVVUlEIjoiNWIzNDg1ODAtNGZmNS0xMWU3LWFjMDYtZDVjZmZmNDZmYzhjIiwicm9sZSI6Im93bmVyIn1dLCJyb2JvdHMiOltdfQ.WOg2otyaNyU1-mlM0wvkAK4hxOVQtfrQw2202G21al8',
authorization = `Bearer ${token}`
let response = await request
.get(uri)
.set('Authorization', authorization)
.accept('application/json')
expect(response.status).to.equal(200)
expect(response.body.data[0].uuid.length).to.be.greaterThan(0)
expect(response.body.data[0].firstName.length).to.be.greaterThan(0)
expect(response.body.data[0].lastName.length).to.be.greaterThan(0)
expect(response.body.data[0].email.length).to.be.greaterThan(0)
})
However In the Browser, when the same type of clal is made from my a UserAPI.js, it fails. I even hard coded a token I know works for sure which is the same token that works in the integration test:
const FindAllUsers = async (token) => {
try {
return await request
.get(url)
.set('Content-Type', 'application/x-www-form-urlencoded')
.set('Authorization', 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0OTk0NDM5NDM5MjMsImV4cCI6MTUwMjAzNTk0MzkyMywidXNlclVVSUQiOiI1YjMyMTQ4MC00ZmY1LTExZTctYWMwNi1kNWNmZmY0NmZjOGMiLCJjc3JBZG1pbiI6dHJ1ZSwiY29nbml0b1VzZXJBcm4iOiJ1cy13ZXN0LTI6NGZjMGFlMDgtNjZhNy00ZDUwLTk2ZDAtOWE3ZmQ0ODAzMWUwIiwicHJvZmlsZXMiOlt7InByb2ZpbGVVVUlEIjoiNWIzNDg1ODAtNGZmNS0xMWU3LWFjMDYtZDVjZmZmNDZmYzhjIiwicm9sZSI6Im93bmVyIn1dLCJyb2JvdHMiOltdfQ.WOg2otyaNyU1-mlM0wvkAK4hxOVQtfrQw2202G21al8')
.accept('application/json')
}
catch(err) {
console.log(err)
}
}
Error I get in the browser:
I know it's not a CORS issue so ignore that, that's a misleading error. So it's hitting that try/catch and failing at the catch which is what you see logged in the browser
I mean I don't think I malformed my syntax in my UserApi at least I don't see anything wrong, it's the same code I pasted from my integration test that worked!
**Server-side REST API Response to OPTIONS request - are we missing something here? **
the server sends back the following on a successful call (say I make a call via my integration test or say postman) for example:
Access-Control-Allow-Headers →Content-Type, Accept
Access-Control-Allow-Methods →GET, POST, DELETE, PUT, PATCH, OPTIONS
Access-Control-Allow-Origin →*
Is it SuperAgent??
Our backend API dev tested in a browser himself (not using superagent) and said it worked for him so wondering if this might be a
superagent syntax issue?
I'm using create-react-app and as far as I know you don't need to worry about setting up anything for CORS.
Why don't I see a request in Chrome tools | Network tab for this?
When I look at this error in chrome and then try to look for the actual GET request for this, I only see an OPTIONS request by the browser. I don't see a request to /users. Why?
The problem is CORS limits headers by default and you do not see "Authorization" header when call CORS requests. So, adjust server to let it send Authorization header in it's settings.
For example in apache httpd:
Header add Access-Control-Allow-Headers "Content-Type, Accept, Authorization, other_header"
Header add Access-Control-Expose-Headers "Content-Type, Accept, Authorization, other_header"
I have a WEB API which I am consuming from POSTMAN, and it works perfectly fine:
Headers:
Content-Type:application/json
X-Developer-Id:asdasdas
X-Api-Key:asdasdas
Authorization:Bearer sasdasdsa
Time-Zone:Morocco Standard Time
When I do a GET request in POSTMAN it works fine, however from angular 2 (Ionic 2) I get the following error:
Request header field Time-Zone is not allowed by Access-Control-Allow-Headers in preflight response.
let params: URLSearchParams = new URLSearchParams();
params.set('date', date);
//Header
let headers = new Headers({
'Content-Type': AppSettings.ContentType,
'X-Developer-Id': AppSettings.XDeveloperId,
'X-Api-Key': AppSettings.XApiKey,
'Time-Zone': AppSettings.time_zone,
'Authorization': AppSettings.Authorization + localStorage.getItem("AccessToken")
});
var RequestOptions: RequestOptionsArgs = {
url: AppSettings.UrlAvailability + userId,
method: 'GET',
search: params,
headers: headers,
body: null
};
return this.http.get((AppSettings.UrlAvailability + userId), RequestOptions)
.map(res => res.json())
.do(data => { data },
err => console.log('error: ' + err));
First I would think that the API developers have to do something on the server side, like enabling that Time-Zone Header on CORS, however if that would be the case then we would get the same error on POSTMAN, but it works fine there.
What am I missing here?
This is something you need to configure on the server. You first need to make sure you have CORS support. I don't use ASP.NET, so I don't know how to do it. I'm pretty sure a quick google search will find you the answer. Then you need to make sure in that server CORS config, that special headers you want the client to be able to send are added to the CORS allowed headers. That's what the error is saying: that the headers are not included in the response header Access-Control-Allow-Headers. The response header would look like
Access-Control-Allow-Headers: X-Developer-Id, X-Api-Key, Time-Zone, Authorization
To learn more about CORS, see the MDN
First I would think that the API developers have to do something on the server side, like enabling that Time-Zone Header on CORS, however if that would be the case then we would get the same error on POSTMAN, but it works fine there
No, Postman does not have the same restrictions. It is a native desktop app. Fun fact: 99% of people who post questions on SO that hava a CORS problem, have somewhere in their post "...but it work with Postman!". So don't feel bad :-)
I think you should remove some of your headers and check you content-type so your request could be considered as a "simple request" and then won't trigger a CORS preflight as explained in the doc.
source:
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#examples_of_access_control_scenarios
Apart from the headers automatically set by the user agent (for example, Connection, User-Agent, or the other headers defined in the Fetch spec as a forbidden header name), the only headers which are allowed to be manually set are those which the Fetch spec defines as a CORS-safelisted request-header, which are:
Accept
Accept-Language
Content-Language
Content-Type (please note the additional requirements below)