I am trying to verify an ID Token using the Firebase Admin SDK as per instructions. My current auth code looks like this (in Vue):
// Auth.vue, inside the firebaseui config callback
signInSuccessWithAuthResult: function(authResult, redirectUrl) {
authResult.user
.getIdToken(/* forceRefresh */ true)
.then(function(idToken) {
// Send token to your backend via HTTPS
// ...
console.log(idToken);
})
.catch(function(error) {
// Handle error
console.log(error);
});
The login works fine and I can get authResult perfectly. However, it seems the function getIdToken is the problem, as I get the following error on my console:
Cross-Origin Request Blocked:
The Same Origin Policy disallows reading the remote resource at
https://securetoken.googleapis.com/v1/token?key=AIzaSyApp5yu051vMJlNLoQ1ngVSd-f2k7Pdavc.
(Reason: CORS request did not succeed).
In my request list, the one hanging is an OPTIONS method, with the following headers:
OPTIONS /v1/token?key=AIzaSyApp5yu051vMJlNLoQ1ngVSd-f2k7Pdavc HTTP/1.1
Host: securetoken.googleapis.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:62.0) Gecko/20100101 Firefox/62.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.8,pt-BR;q=0.5,de;q=0.3
Accept-Encoding: gzip, deflate, br
Access-Control-Request-Method: POST
Access-Control-Request-Headers: x-client-version
Origin: http://localhost:8080
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
I am not even sure where the problem lies. Is it coming from the Vue side? I am running it in a dev server (by simple yarn serve, vue cli 3). Would the solution be when I run Vue on a production server where I can actually configure cors?
Any light on the matter is extremely welcome...
Thanks!!
Figured it out.
I was calling it in the wrong place. What helped was this thread, which pointed me out to Preflighted Requests which is what the OPTIONS request is:
"preflighted" requests first send an HTTP request by the OPTIONS method to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests are preflighted like this since they may have implications to user data.
So I realized I should not be sending this request within my Post request where I got the authorization in the first place. Moving it to another method made it work.
Related
I'm trying to authenticate a user with JWT using GraphQL. Once I login the user I receive the token as a JSON response and a httponly cookie storing the refresh token. (Server-side is using Saleor-core)
From the documentation of Saleor and some other blog-posts I assume that this response cookie should now be stored in the browser and whenever I need to refresh a token the cookie-refreshToken is used to authenticate my request. However, when I switch tabs to "Application" in my dev tools it's just empty.
What is the normal behaviour of the browser after receiving a cookie response? Do I need some extra code to somehow "save" that response cookie?
Did not really find anyone else having this problem so I think the mistake must be somewhere else.
UPDATE
I read somewhere the issue might be that there is no "secure" flag, which resulted from the server debug mode. I turned it off, but the cookie is still not being set.
Response Headers:
HTTP/1.1 200 OK
Connection: keep-alive
Date: Thu, 23 Sep 2021 13:32:33 GMT
Server: uvicorn
Content-Type: application/json
Access-Control-Allow-Origin: https://rewhite-86006--beta-duoa0dwg.web.app
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Headers: Origin, Content-Type, Accept, Authorization, Authorization-Bearer
Access-Control-Allow-Credentials: true
Content-Length: 912
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Set-Cookie: refreshToken=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2MzI0MDM5NTQsIm93bmVyIjoic2FsZW9yIiwiZXhwIjoxNjM0OTk1OTU0LCJ0b2tlbiI6Ijd2b0VmMm1DNlZZSyIsImVtYWlsIjoiSnVsaWFuLkZpbmtlQGdtYWlsLmNvbSIsInR5cGUiOiJyZWZyZXNoIiwidXNlcl9pZCI6IlZYTmxjam8zTmc9PSIsImlzX3N0YWZmIjpmYWxzZSwiY3NyZlRva2VuIjoiWm55ek9xVG9rOU9GYXlDZXY0cjFxMUxnaktnTXRRR0VNUVJEalR1eTJDZ1IyOW1GSVBxQ1B1T1hZcTFQNk92cyJ9.Cl6PmoLkO9Hlh36tDOuyNLQCib4FVBwn32hhnmd7Q4E; expires=Sat, 23 Oct 2021 13:32:34 GMT; HttpOnly; Max-Age=2592000; Path=/; Secure
Via: 1.1 vegur
Request Headers:
POST /graphql/ HTTP/1.1
Host: rewhite-saleor-engine.herokuapp.com
Connection: keep-alive
Content-Length: 318
Pragma: no-cache
Cache-Control: no-cache
sec-ch-ua: "Google Chrome";v="93", " Not;A Brand";v="99", "Chromium";v="93"
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36
sec-ch-ua-platform: "macOS"
content-type: application/json
Accept: */*
Origin: https://rewhite-86006--beta-duoa0dwg.web.app
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://rewhite-86006--beta-duoa0dwg.web.app/
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
Thanks for your help!
The Domain attribute on you cookie seems to be different from the origin of your request. You're making a cross-site request and receiving a Set Cookie response from the server (of a different domain).
Normally we run into this issue when running backend and frontend on different domains (for e.g. localhost:3000 and localhost:8080).
Solution:
Recent Chrome browser versions (from 2020) will only set cookies received from cross-site requests if cookie has SameSite=None and Secure attributes set. With Secure set, a cookie will only be sent to server over HTTPS protocol (you need to implement SSL).
As of now, you don't have set either. SameSite defaults to Lax not None. You need to explicitly set it.
OR
You need implement a proxy such that you will request your webapp on https://rewhite-86006--beta-duoa0dwg.web.app and your webapp will proxy this to your Saleor engine domain rewhite-saleor-engine.herokuapp.com. How you do that depends on what frameworks you're using for serving your webapp. You haven't mentioned your it in your question, but I notice you've tagged it under vue.js, so I'll assume that you're using Vue CLI for serving a Vue app.
Its very simple to set up a proxy with Vue CLI. Just look for vue.config.js file in your root directory. If its not there, create it and paste the code below:
module.exports = {
devServer: {
proxy: {
'^/graphql': {
target: 'https://rewhite-saleor-engine.herokuapp.com',
changeOrigin: true,
logLevel: 'debug',
},
},
},
}
Now instead of fetching the refreshToken from rewhite-saleor-engine.herokuapp.com/graphql, you should send the request to your webapp at https://rewhite-86006--beta-duoa0dwg.web.app/graphql, and your web app local server will forward the request to your Saleor backend on Heroku. To your browser it will appear as though the request's response came form the webapp itself, so it won't be a cross-site request anymore.
I am trying to test an API hosted using AWS API Gateway and always getting following error:
Error: socket hang up
Request Headers
clientId: system
Authorization: //Correct Auth Token
User-Agent: PostmanRuntime/7.26.8
Accept: */*
Host: //API Host URL
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
However, when I pass in an invalid Auth Token (like TEST), I actually receive a 403 error as expected. I can also see logs in CloudWatch confirming the call reached the authorizer.
CloudWatch Logs
The same API works for other people perfectly fine.
I have tried almost every resolution I found online related to this issue like I turned off 'SSL Certificate Verification' in Postman and kept proxy settings same as my colleagues. Tried to hit the API after disconnecting VPN as well but nothing worked for me.
Could anyone please help me with this.
Thanks in advance.
I am getting "The remote server returned an error: (401) Unauthorized." when using the servicestack utils to call a remote API. It requires auth basic or JWT. Calling the same API from PostMan works fine.
var json = $"http://localhost:5000/API/Proxy/IsValidGuidForSetupDevice?Guid=82870f2ca21148739bff0854b306415c".GetJsonFromUrl(requestFilter: webReq => { webReq.AddBasicAuth("DevAdmin", "test1"); });
if i call below with the same user pass in a browser window. i get a valid connect and a bearer token back. The user\pass is good.
http://localhost:5000/auth/credentials?username=DevAdmin&password=test1&format=json
AM I missing something in request filter of the Util? Maybe I should be calling it differently and using a bearer token?
Update after tracing with fiddler
I moved the code into a unit test in the same project as the servicestack service. Just to remove any variables.
Fiddler shows me that : No Proxy-Authenticate Header is present. WWW-Authenticate Header is present: Basic realm="/auth/apikey" GET http://localhost:5000/auth
Raw View
HTTP/1.1
Host: localhost:5000
Connection: keep-alive
Accept: application/json, text/javascript, */*; q=0.01
DNT: 1
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Referer: http://localhost:5000/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: ss-opt=perm; loginLevel=none; X-UAId=2; ss-id=XPc7ivcCrXuN5tEWwARG; ss-pid=TDeEjUiKck82foJGLGtX
Playing around with it. I can get it to login by calling the URL directly with user and pass. The i get the bearer token back and I am able to pass it.
var json = $"http://localhost:5000//auth/credentials?username=DevAdmin&password=test1".GetJsonFromUrl();
var o = JsonObject.Parse(json);
var token = o.Get<string>("bearerToken");
var jsonr = $"http://localhost:5000/API/Proxy/IsValidGuidForSetupDevice?Guid=bc464658d6a640febbd53ba17c351919".GetJsonFromUrl(
requestFilter: webReq => { webReq.AddBearerToken(token); });
I still can't call this in one call with auth headers and I still don't know why.
Whenever diagnosing different behavior between HTTP Requests of different clients you should inspect the raw HTTP Traffic between the different clients using a HTTP Packet sniffer like Fiddler or WireShark, or if the request is made from a browser you can use their built-in Web Network Inspector tools.
Seeing and comparing raw HTTP Request/Responses are the best way to identify how the requests differ.
The AddBasicAuth() extension method lets you add HTTP Basic Auth to the Web Request, if you want to send the JWT Token instead you would use the AddBearerToken() method instead.
A page at http://www4.example.com that tries to an xhr connection to http://www6.example.com/
The browser sends a GET request with this header:
Origin: http://www4.example.com
The www6.example.com server sends back:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://www4.example.com
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/plain
Date: ...
Keep-Alive: timeout=5, max=100
Transfer-Encoding: Identity
Server: Apache/2.2.20 (Ubuntu)
Vary: Accept-Encoding
X-Powered-By: PHP/5.3.6-13ubuntu3.7
And yet I get:
XMLHttpRequest cannot load http://www6.example.com/myscript.php?xhr=1&t=1234333223. Origin http://www4.example.com is not allowed by Access-Control-Allow-Origin.
My code matches my understanding of the CORS standard, and works fine with Chrome, Firefox, Opera, etc. so I'm going to assume this is a Safari 5.1 bug? My question is what do I need to do to work around it?
After a lot of trial and error, and watching network traffic, I think I can self-answer.
The Safari bug is that it sends an OPTIONS pre-flight request first, even though it is a GET request.
To add some extra complexity, it appears to only send this on the 2nd request. (I think this is because my 2nd request sends an extra custom header... but I couldn't actually isolate that, so I think there is something else going on as well - perhaps cache interactions?)
Sending Access-Control-Allow-Headers in the main response does not fix the problem: it does the OPTIONS request first, so never gets that far.
The fix I did was to put this at the very top of the PHP script:
if($_SERVER['REQUEST_METHOD'] == 'OPTIONS'){
header("Access-Control-Allow-Origin: ".#$_SERVER['HTTP_ORIGIN']);
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Headers: Last-Event-Id, Origin, X-Requested-With, Content-Type, Accept, Authorization");
exit;
}
Sending back "Access-Control-Allow-Headers: *" did not work. You have to explicitly list the headers you want. I briefly experimented and it appears they are case-insensitive.
Sending back "Access-Control-Allow-Methods: POST, GET, OPTIONS" was not needed.
As an aside, Cookies are sent, but basic auth details are not sent (despite explicitly listing the Authorization header there). This might be a deliberate limitation of the CORS implementation, as of this version of WebKit (534.57.2), not a bug.
I'm currently trying to connect to a webservice placed on https://xxx.xxx.xx/myapp
It has anonymous access and SSL enabled for testing purposes atm.
While trying to connect from the 3G network, i get Status 403: Access denied. You do not have permission to view this directory or page using the credentials that you supplied.
I get these headers while trying to connect to the webservice locally:
Headers
Request URL:https://xxx.xxx.xx/myapp
Request Method:GET
Status Code:200 OK
Request Headers
GET /myapp/ HTTP/1.1
Host: xxx.xxx.xxx
Connection: keep-alive
Authorization: Basic amViZTAyOlE3ZSVNNHNB
User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: sv-SE,sv;q=0.8,en-US;q=0.6,en;q=0.4
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Response Headers
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Server: Microsoft-IIS/7.0
X-Powered-By: ASP.NET
Date: Thu, 16 Feb 2012 12:26:13 GMT
Content-Length: 622
But when accessing outside the local area, we get the big ol 403. Which in turn wants credentials to grant the user access to the webservice.
However, i've tried using the ASIHTTPRequest library without success, and that project has been abandoned. And they suggest going back to NSURLConnection.
And i have no clue where to start, not even which direction to take.
-connection:(connection *)connection didRecieveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
The above delegate method of NSURLConnection doesnt even trigger. So i have no idea what so ever how to authenticate myself.
All i get is the parsed results of the xml elements of the 403-page.
I needs dem seriouz helps! plx.
This was all just a major f-up.
The site had ssl required and enabled, and setting ssl required for the virtual directories does some kind of superduper meta-blocking.
So, by disabling ssl required for the virtual directories, it runs over ssl and is not blocking 3G access..