I'm trying to create an OAuth integration with Workday, but am receiving an Unauthorized Client error. I enabled the API client, got secret and access keys, and configured a redirect URI pointing to my server.
When I visit https://impl.workday.com/myTenant/authorize?response_type=token&client_id=myClientID, I'm brought to a screen to allow this app access to my Workday, I hit accept, and am then redirected to my server. However, when I check my server logs showing the request URL and headers, this is what I'm seeing:
URL: /workday?error=unauthorized_client
Headers: { host: 'localhost:9001',
connection: 'close',
'cache-control': 'max-age=0',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36',
'sec-fetch-mode': 'navigate',
'sec-fetch-user': '?1',
accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
'sec-fetch-site': 'cross-site',
referer: 'https://impl.workday.com/wday/authgwy/myTenant/authorize?response_type=token&client_id=myClientID',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-US,en;q=0.9'
}
I expected to receive a header "Location: https://example.com/#access_token=someAccessToken&token_type=Bearer" but am getting the unauthorized client error.
Changing https://impl.workday.com/myTenant/authorize?response_type=token&client_id=myClientID to https://impl.workday.com/myTenant/authorize?response_type=code&client_id=myClientID solved the issue.
Related
I am trying to send a post request using Javascript, but the problem is that I do not seem to be able to add custom headers to the request.
The request that I want to send:
OPTIONS /startScan?domain=asite.com&user=38 HTTP/2
Host: MYHOST
Accept: */*
Access-Control-Request-Method: POST
Authorization: A_TOKEN
Origin: http://localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
Sec-Fetch-Dest: empty
Referer: http://localhost/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
note that MYHOST and A_TOKEN are in my case other values, but replaced them for security reasons.
The request that I send:
OPTIONS /startScan?domain=asite.comm&user=38 HTTP/2
Host: MYHOST
Accept: */*
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization,content-type
Origin: http://localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
Sec-Fetch-Dest: empty
Referer: http://localhost/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
The code that I use to send this:
var data = JSON.stringify({
"domain": "asite.com",
"user": 38
});
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function() {
if(this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open("POST", "MYHOST/startScan?domain=asite.com&user=38");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Authorization", "A_TOKEN");
xhr.send(data);
The problem:
The problem now is that I am not able to add a custom header to this request. Instead of adding a header that is called Authorization I add a Access-Request-Control-Header which has authorization as value. I have tried using jQuery, XHR (as you can see) and Fetch, but no success with all of them.
Can anyone help me?
I send a request with javaScript. If I send it this way
var request = new XMLHttpRequest();
request.open("POST",/*some url*/);
/*here's nothing*/
request.addEventListener('load', function(event) {/*some magic*/});
request.send();
Chrome shows me this request headers as sent:
:authority: <some data>
:method: POST
:path: /
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
content-length: 0
origin: <some data>
referer: <some data>
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: same-site
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36
If I try to add another header (by replacing /here's nothing/ with
request.setRequestHeader("auth", "token");
the request header sent seems to loose some data. It now consists of:
auth: token
Referer: <some data>
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36
The "origin" get's lost, but I need it for my CORS handling. So why the hell does it get lost?
Any ideas appreciated
Thnaks #John for leading me this way:
Actually, XMLHttpRequest or fetch doesn't matter. But the fetch documentation lead me the right way.
The problem was, that my sever answered the "OPTIONS" request with a http 400, what messed up preflight. I adjusted it, so it handles CORS at an OPTIONS request correctly and sends it with a HTTP 200 and now everything works smoothly.
I have a react application connecting to a Spring Boot backend application, I use JWT to authorize the user at the backend. I am using fetch to make the calls between the front and backend.
Whenever I try to set the headers of the call all the headers get removed including the Cookie (which contains the JWT). I need to set the headers to specify the content-type of the request.
- Call when I do not set the headers (causing 415)
fetch code:
return fetch(`${urlApiGateway}${url}`, {
method: "POST",
body: body,
credentials: "include",
})
Call:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,nl-NL;q=0.8,nl;q=0.7
Connection: keep-alive
Content-Length: 13
content-type: text/plain;charset=UTF-8
Cookie: Authorization=Bearer_eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJjYXNwZXIubS50b3JlbjJAZ21haWwuY29tIiwiZXhwIjoxNjI1NDg2MzAzLCJpYXQiOjE2MjUzOTk5MDMsInVzZXIiOnsiaWQiOjIsIm5hbWUiOiJjYXNwZXIiLCJlbWFpbCI6ImNhc3Blci5tLnRvcmVuMkBnbWFpbC5jb20iLCJwYXNzd29yZCI6IiIsInBlcm1pc3Npb25zIjoiQURNSU4ifX0.JdW1M7d8HB71yvP7dupomN-bgD_484HHbxmfnOOmvqM
Host: localhost:8080
Origin: http://localhost:3000
Referer: http://localhost:3000/
sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
sec-ch-ua-mobile: ?0
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
As you can see the headers are present like 'content-type' and 'Cookie'.
- Call when I do set the headers to prevent 415
fetch code:
return fetch(`${urlApiGateway}${url}`, {
method: "POST",
body: body,
headers: { "Content-Type": "application/json" },
credentials: "include",
})
Call:
It seems to be making 4 call, 2 with the previous fetch settings which where the same (no headers set).
2 of the calls look like this
Provisional headers are shown
content-type: application/json
Referer: http://localhost:3000/
sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
and 2 look like this
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,nl-NL;q=0.8,nl;q=0.7
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Connection: keep-alive
Host: localhost:8080
Origin: http://localhost:3000
Referer: http://localhost:3000/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
Where, as you can see, the headers are gone including the Cookie and content-type.
- Spring boot cors
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins(allowOrigin, "http://localhost:3000")
.allowCredentials(true)
.allowedHeaders("*")
.allowedMethods("GET", "POST", "OPTIONS");
}
I hope someone can help :)
You must pass Authorization Bearer token as header. Try this:
let yourAuthToken = .... // get bearer token from where you store it
return fetch(`${urlApiGateway}${url}`, {
method: "POST",
body: body,
headers: {
'Authorization' : 'Bearer ' + yourAuthToken
}
})
It hadn't anything to do with the js code, it was my cors settings on the backend side. My authorization filter was also being applied to the OPTIONS request which caused a cors error (no http ok status), after changing this it was fixed.
Thank you to all who tried to help me.
I have created on JS SPA which calls Web API. I am using CORS to allow all request for Web Api using tag "assembly: OwinStartup" and "app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);"
Complete application here
For Edge request is successful whereas in Chrome it is not. I am getting error: Failed to load https://localhost:44373/api/location?cityName=dc: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://localhost:44392' is therefore not allowed access.
Interesting part is I am unable to see any "Access-Control-Allow-Origin" request header for both in Developer tool.
For Chrome:
:authority:localhost:44373
:method:GET
:path:/api/location?cityName=dc
:scheme:https
accept:application/json, text/plain, /
accept-encoding:gzip, deflate, br
accept-language:en-US,en;q=0.9,bn;q=0.8
cache-control:no-cache
origin:https://localhost:44392
pragma:no-cache
referer:https://localhost:44392/
user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36
For Edge:
Accept: application/json, text/plain, /
Accept-Encoding: gzip, deflate, peerdist
Accept-Language: en-US
Host: localhost:44373
Origin: https://localhost:44392
Referer: https://localhost:44392/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393
X-P2P-PeerDist: Version=1.1
X-P2P-PeerDistEx: MinContentInformation=1.0, MaxContentInformation=2.0
My start up page looks like this
You have to use this line of code as the first statement in the startup class --
public void Configuration(IAppBuilder app)
{
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
...
...
...
My guess for it "working" in Edge is because it's detected localhost and decided not to do a CORS check; but Chrome will always do the check.
Anyways, you're not seeing the header because its not there. To get it working, do the following:
Add these 2 packages: Microsoft.AspNet.WebApi.Owin and Microsoft.Owin.Host.SystemWeb
Comment out GlobalConfiguration.Configure(WebApiConfig.Register); from the global.asax file because we want to use OWIN for Web API.
Replace Configuration() with this code in your StartUp:
public void Configuration(IAppBuilder app)
{
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
app.UseWebApi(config);
}
I have written a servlet Filter in which I am trying to get the value of custom header=samlRequest, From rest client/postman chrome plugin i am getting the value of samlRequest, but using ajax call i have provide samlRequest key and its value but in java i am getting the only key samlRequest in "Access-Control-Request-Headers", how to get value of samlRequest.
$.ajax({
url: "http://indlin500.corp.test.com:31000/test/Portal/index.html",
type: "GET",
headers: { 'samlRequest': 'eJzVWVlz4roSfs6/oJhHJvECBkMRTsk2+2ow68stY8u2wBuWjQ2//srsyUlmJufOramTSjm41f '},
beforeSend: function(xhr){xhr.setRequestHeader('samlRequest', 'eJzVWVlz4roSfs6/oJhHJvECBkMRTsk2+2ow68stY8u2wBuWjQ2//srsyUlmJufOramTSjm41f ');},
success: function() { alert('Success!' + authHeader); }
});
FirewalledRequest[
weblogic.servlet.internal.ServletRequestImpl#4f839843[ OPTIONS
/testsOSS/Portal/index.html HTTP/1.1 Connection: keep-alive
Access-Control-Request-Method: GET Origin: http://10.19.121.17:7001
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Access-Control-Request-Headers: authorization, samlrequest,
x-partnerkey Accept: / DNT: 1 Referer:
http://10.19.121.17:7001/authentication-uxf-login-0.0.1-SNAPSHOT/customLoginPage.html Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8
]]
Using chrome rest client plugin I am getting samlRequest in the header with value i have provided.
FirewalledRequest[
weblogic.servlet.internal.ServletRequestImpl#24d746a[ GET
/testOSS/Portal/index.html HTTP/1.1 Connection: keep-alive
Cache-Control: no-cache samlRequest: eJzVWVlz4roSfs6/oJhHJvECBkMRTsk2+2ow68stY8u2wBuWjQ2//srsyUlmJufOramTSjm41f User-Agent: Mozilla/5.0
(Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/55.0.2883.87 Safari/537.36 Postman-Token:
ce7765d0-94b5-a1e1-d6ba-2abada3dfdd6 Accept: / DNT: 1
Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8
]]
When you make a cross-origin request from browser, the browser makes a preflight request before the actual request. It is an OPTIONS request, unlike the intended GET request.
Try adding a CORS filter before the actual filter which will reply OK for any OPTIONS request. A sample code can be found here :
https://amodernstory.com/2014/12/27/using-cors-headers-with-java-example/
by the way, you don't need to set header in request twice. You can remove the beforeSend block from the ajax request.