JIRA Cloud REST API (OAuth 2.0) Error 403 on POST Requests - reactjs

I am trying to connect my React app to the Jira Cloud API and can't seem to get past a 403 error.
My code currently does a Auth dance using OAuth 2.0 and returns the token and cloudid. I can use this to GET issues, however POST request (like creating an issue) return with 403. I have found here that this error is returned if the user does not have the necessary permission to access the resource or run the method.
I have ensured the user has the correct scope ([write: jira-work, read: jira-work]) and verified this is reflected in the user account (in their account > connect apps tab).
My app is not linked (via ApplicationLink) or installed (via Apps, Manage Apps), is this necessary to perform POST requests?
Here is a sample of my code:
fetch(`https://api.atlassian.com/ex/jira/${jira.cloudid}/rest/api/2/issue/`, {
method: "POST",
headers: {
"Content-Type": 'application/json',
"Authorization": `Bearer ${jira.token}`
},
body: JSON.stringify(data)
})
.then(...)
Neither api version 2 or 3 are working for this POST request. I have explored using Basic Auth however this fails due to CORS errors.
I have verified that the POST request does work in POSTMAN (using the cloudid and token).
---------------------------------------------------------------------------------------------------------------------------
UPDATE
After talking to Atlassian Staff, there is an issue within their API security:
"By trying the same thing you mentioned I think I found what the problem is. Your request likely fails with a ‘XSRF check failed’ in the browser.
I’ve already talked to one of our security engineers and we quickly dived into the implementation code to confirm why this not working and what would need to be changed on our side. We’ve also already opened a engineering ticket to get this addressed. This will likely take a few weeks to get addressed, but I’ll keep you posted if I hear any updates!"
The XSRF check failed was the main error for my 403 response. I'll post any updates I receive and answer the question when a resolution is found.

This has apparently been resolved. Follow the discussion here: https://community.developer.atlassian.com/t/jira-cloud-rest-api-oauth-2-0-error-403-on-post-requests/25621/4

Related

IdentityServer API unauthorized if hosted in IIS

I added additional API to the Duende IdentityServer 6.2 as described here. Then I tried to access it from a sample App, using typed httpClient using their own library called AccessTokenManagement (aka Identity.Model) pretty much following their simple example. I use Authorization Code flow, everything pretty much simple and default.
It works well until both server and client are on the same dev machine under localhost. As soon as I publish IdentityServer to IIS, the API stops to work, while the rest still works well (I can be authenticated, and I see in the Fiddler that token exchanges work normally).
The call to API consists from two calls:
Calling to /connect/token using refresh token. Server returns access token.
Calling my endpoint using this new access token.
The flow fails on the step 1. Call to /connect/token is already unauthorized and I can't understand why. The "good" and "bad" calls looks the same, I cannot see any differences. Previous call moment ago to /connect/userinfo consists of the same two steps and it works. Logs on both server and client give no clues.
No reverse proxies, just good plain simple URI. Automatic key management is enabled and the keys are in the SQL table, common for dev and published server. Asp.Net Core Data Protection is enabled and keys are also common.
Relevant parts of logs are below. I noticed that "No endpoint entry found for request path" is specific to IdentityServer and it doesn't actually mean that endpoint was not found. It was found but not processed. I also noticed reacher response headers from bad request and log entry about "Cookie signed-in" in good request but not sure what does it mean and whether it's relevant.
I'm running out of ideas.
Bad response from IIS while trying to get new Access Token:
Proper response while developing:
///////Relevant part of log for BAD request
|Duende.AccessTokenManagement.OpenIdConnect.UserAccessAccessTokenManagementService|Token for user test#test.com needs refreshing.
|Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler|AuthenticationScheme: cookie was successfully authenticated.
|Duende.AccessTokenManagement.OpenIdConnect.UserTokenEndpointService|refresh token request to: https://auth.mysite.org/connect/token
|Duende.AccessTokenManagement.OpenIdConnect.UserAccessAccessTokenManagementService|Error refreshing access token. Error = Unauthorized
|System.Net.Http.HttpClient.IdsService.ClientHandler|Sending HTTP request POST https://auth.mysite.org/mycontroller/myaction
|System.Net.Http.HttpClient.IdsService.ClientHandler|Received HTTP response headers after 117.7278ms - 401
///////Same part of GOOD request
|Duende.AccessTokenManagement.OpenIdConnect.UserAccessAccessTokenManagementService|Token for user test#test.com needs refreshing.
|Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler|AuthenticationScheme: Cookies was successfully authenticated.
|Duende.AccessTokenManagement.OpenIdConnect.UserTokenEndpointService|refresh token request to: https://localhost:5001/connect/token
|Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler|AuthenticationScheme: Cookies signed in.
|System.Net.Http.HttpClient.IdsService.ClientHandler|Sending HTTP request POST https://localhost:5001/mycontroller/myaction
|System.Net.Http.HttpClient.IdsService.ClientHandler|Received HTTP response headers after 1994.9611ms - 200
///////Server log during BAD request
Duende.IdentityServer.Hosting.EndpointRouter No endpoint entry found for request path: "/mycontroller/myaction"
Duende.IdentityServer.Hosting.LocalApiAuthentication.LocalApiAuthenticationHandler HandleAuthenticateAsync called
Duende.IdentityServer.Hosting.LocalApiAuthentication.LocalApiAuthenticationHandler AuthenticationScheme: "IdentityServerAccessToken" was not authenticated.
Duende.IdentityServer.Hosting.LocalApiAuthentication.LocalApiAuthenticationHandler AuthenticationScheme: "IdentityServerAccessToken" was challenged.
Okay, found it. Thankfully, looked at Fiddler's WebView and had seen familiar picture!
Then, found this topic. The solution was disabling Basic authentication in IIS settings. Access token request has basic authentication header and it seems like IIS intercepts it. Still a bit unclear why other parts of flow worked.

(NodeJS / AngularJS) POST request with 'x-auth' token to server, but token seems to get lost in preflight (no error though)

Background
I have a simple NodeJS server hosted on localhost/Heroku which handles JWT authentication for adding data to the registered user amongst other (unrelated) things.
Here's the GitHub: https://github.com/mlee93dev/pw-keychain-server
I also have a simple Angular2 client on localhost/Heroku for this server:
https://github.com/mlee93dev/pw-keychain-app
Currently, I have my JWT access tokens configured to last only 5 seconds in my server for development purposes.
I have my CORS stuff configured to the best of my knowledge as shown below in server.js:
CORS configuration pic
The Problem
On Postman I test the POST request and I get the expected response - a JWT expiration error:
Postman POST pic
However I don't get the same response on my client - rather, I get a 'JWT must be provided' error:
Client POST pic
As you can see in the pic above, I know I'm actually attaching a token as I console.log it. Here's a pic of the code:
Client POST code pic
So what's confusing me more is that my DELETE request (for logging out) also implements the same x-auth token to request code, and it works in both Postman + client, as seen here:
DELETE error response
DELETE code
So yeah, I'm pretty confused. My guess is I have to configure my CORS some more to allow x-auth header on POST requests specifically somehow? Even though I think it should do that already with my current configuration.
You are providing the body in post request instead of headers.
Angular POST request
So in your post request just do the following
this.http.post(yoururl, {},{headers:new Headers({'x-auth':token})})...
And it should work.

Express API with JWT returns "Unauthorized: Invalid Algorithm error"

I've written a simple React app, following the instructions of a slightly out of date tutorial that is meant to display a list of contacts in the sidebar with individual contact data displayed in an index component but only if you have been authenticated by logging into an Auth0 component and have a JSON Web Token kept in local storage. I have confirmed that I am logged in and have the token. Everything up to this point is working fine.
The problem begins when I click on a contact in the sidebar to view that contact's data, which comes down from a pretty basic API set up with Express. I've been using Postman to troubleshoot since the only error I get from app is "401: Unauthorized"
When I hit my endpoint, suppling an Authorization header with "Bearer [JWT_VALUE_HERE]" Postman responds with "UnauthorizedError: invalid algorithm"
The full output
UnauthorizedError: invalid algorithm
at /Users/Arkham/Documents/Web/eldrac/react-auth-server/node_modules/express-jwt/lib/index.js:102:22
at /Users/Arkham/Documents/Web/eldrac/react-auth-server/node_modules/jsonwebtoken/verify.js:27:18
at _combinedTickCallback (internal/process/next_tick.js:95:7)
at process._tickCallback (internal/process/next_tick.js:161:9)
I've done a bit of googling and tweaked my Auth0 client settings, specifically the Algorithm settings but no matter what I set it to (my options are RS256 and HS256), it doesn't seem to make a difference. I'm dying to get past this.
I use Superagent to make my request
getContact: (url) => {
return new Promise((resolve, reject) => {
request
.get(url)
.set('Authorization', 'Bearer ' + AuthStore.getJwt())
.end((err, response) => {
if (err) reject(err);
resolve(JSON.parse(response.text));
})
});
}
Which seems to be working. I have confirmed that the url is correct and that AuthStore.getJwt() are supplying the correct parameters.
Your question does not provide much information necessary to diagnose the issue - First of all, you should be sending a JWT Access token to the API, not your Id Token.
Upfront questions:
Do you have an API defined in the Auth0 Dashboard?
When you authenticate, are you using an audience parameter? It is
likely that the Access Token is using RS256. Remember for an access
token and Resource API, it is the API that controls the algorithm,
not the Client.
What algorithm is your API using to verify the token?
Presumably, the url in your code snippet is something like
http://localhost:3001/myendpoint?
Take your token, and paste it at https://jwt.io to see what the algorithm used is. Compare that with what is being used to verify the token.
Shall update my answer here as you give more information - please use comments section for this answer.

400 Bad Request if Authorization Bearer token used

I'm using PostMan to troubleshoot an odd 400 error with my Angular / NodeJS app.
I'm trying to GET https://example.com/login.html and the request has two headers:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...== and Accept: text/html
This returns a 400 Bad Request error (server: cloudflare-nginx)
This works fine (returns 200) if:
I access the file in my local environment on http://localhost:5000/login.html (no https factor?) -or-
I remove Authorization: Bearer from the header
If I watch my NodeJS server logs, I don't even see the request come through. So /login.html doesn't even get hit, I assume because Express is rejecting it before my app.use(logger('dev')); picks it up.
UPDATE: I believe Cloudflare is kicking it back with 400 prior to the request ever reaching Heroku.
A few more points:
I am using JWT to authenticate users, which is where the Bearer token comes from.
If I access other endpoints, such as /profile with the Bearer token, it responds properly with the user profile from decoding the token.
My question is:
Why would this request be a "Bad Request" when it works on other endpoints?
Is there a way to catch this and do something with the request before it's returned as 400?
As it turns out, the issue was related to my implementation of JWT. For some reason, one user continued to receive a token that caused these 400 errors, even though the token was verified as valid using JWT.io.
I made two significant changes that fixed the issue:
I was embedding the full user profile (long JSON) in the token payload. I reduced it to just their userid, both for performance reasons (far smaller size) and just in case something in the complex payload was causing the issue.
I switched from JWT-Simple to jsonwebtoken in my node implementation.
I'm just glad that worked. My next step was to switch from 'Authorization' to 'x-encoded-auth' or some other custom name.
#James, I don't have enough reputation to post a comment on your answer, but I thought it would be helpful to others struggling with this issue to state that your suggestion to reduce the complexity/size of the signed user indeed resulted in resolving similar issues I was experiencing. This was on my list of performance optimizations anyway - but it didn't occur to me that it could be a cause for error in this scenario - so you deserve the credit... thanks!
For readers - there are some useful links in this SO thread about max size for tokens: What is the maximum size of JWT token?
And this is a tool I use to check the validity of a generated tokens... https://www.base64decode.org/
Hope this justifies the upgrade from comment to answer!

Open Graph Action POST fails when called thru a google app engine based unpaid instance

urlopen fails with a 500 code and '{"error_code":1,"error_msg":"An unknown error occurred"}' error from Facebook when posting an Open Graph Action. I can get the code to work with other posts (e.g. posting a comment on a status using the graph API works fine). I can also get this action-post to work using curl. So this seems like a urllib2.urlopen issue when posting a form-data with a URL as one of the values.
Graph api post that works with curl :
curl -F 'access_token=nnnnnn' -F 'object=https://abc.com/123' \
'https://graph.facebook.com/me/namespace:action' -k
Same Graph api post thru urllib2 which gives the error :
from urllib2 import urlopen, Request, URLError
request = Request (url='http://graph.facebook.com/me/namespace:action';,
data = urllib.urlencode(
{'object':'https://abc.com/123',
'access_token':'nnnnnnnn'
},
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
)
response = urlopen (request)
What could I be doing wrong ? (I am new to urllib2.urlopen. Btw, I originally tried urlfetch.fetch thru the urlfetch python module. That did not work either). I am using this thru goole app engine.
After a fair amount of digging/trial-error, finally managed to solve this.
This is not an issue with urllib urlopen, but more of a Google App Engine nuance where when an action post on an open Graph URL is called - it causes Facebook to trigger a 'get' on the Object URL (synchronously).
So essentially the get is being called on app engine app while an active instance is already calling the FB graph URL. I am currently using an unpaid instance and this is causing an unexpected behavior such that FB to fails the OG post (I see the get on the logs going thru successfully, while the active post, so not sure what causes FB to fail - anybody with an insight, please share).
I got around this by 'taskqueue'ing urlopen/OG-action-post - and when this is called the second time (FB apparently caches the object the first time) it succeeds.
If anybody needs more details, get in touch and am more than happy to save you all the time and pain that I have already gone thru..

Resources