How to pass JWT on header with Swagger - node.js

I'm learning Swagger, Express.js and JWT with those tutorial sites.
https://scotch.io/tutorials/speed-up-your-restful-api-development-in-node-js-with-swagger
https://scotch.io/tutorials/authenticate-a-node-js-api-with-json-web-tokens#creating-a-sample-user
And the end of the article, there is a challenge to rewrite the Swagger tutorial with JWT.
I'm doing it and stuck in a problem.
My problem is that Server side(Express.js) can't get the header parameter which i set on swagger web interface.
console.log("req.headers : %j", req.headers); outputs the following log.
req.headers : {"host":"localhost:10010","connection":"keep-alive","access-control-request-method":"POST","origin":"http://127.0.0.1:49729","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36","access-control-request-headers":"content-type, token","accept":"*/*","referer":"http://127.0.0.1:49729/","accept-encoding":"gzip, deflate, sdch","accept-language":"ja,en-US;q=0.8,en;q=0.6"}
There is no "x-access-token", right?
So i tested with Postman, and i got this log.
req.headers : {"host":"localhost:10010","connection":"keep-alive","content-length":"0","cache-control":"no-cache","origin":"chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop","x-access-token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyIkX18iOnsic3RyaWN0TW9kZSI6dHJ1ZSwiZ2V0dGVycyI6e30sIndhc1BvcHVsYXRlZCI6ZmFsc2UsImFjdGl2ZVBhdGhzIjp7InBhdGhzIjp7Il9fdiI6ImluaXQiLCJwYXNzd29yZCI6ImluaXQiLCJlbWFpbCI6ImluaXQiLCJuYW1lIjoiaW5pdCIsIl9pZCI6ImluaXQifSwic3RhdGVzIjp7Imlnbm9yZSI6e30sImRlZmF1bHQiOnt9LCJpbml0Ijp7Il9fdiI6dHJ1ZSwicGFzc3dvcmQiOnRydWUsImVtYWlsIjp0cnVlLCJuYW1lIjp0cnVlLCJfaWQiOnRydWV9LCJtb2RpZnkiOnt9LCJyZXF1aXJlIjp7fX0sInN0YXRlTmFtZXMiOlsicmVxdWlyZSIsIm1vZGlmeSIsImluaXQiLCJkZWZhdWx0IiwiaWdub3JlIl19LCJlbWl0dGVyIjp7ImRvbWFpbiI6bnVsbCwiX2V2ZW50cyI6e30sIl9ldmVudHNDb3VudCI6MCwiX21heExpc3RlbmVycyI6MH19LCJpc05ldyI6ZmFsc2UsIl9kb2MiOnsiX192IjowLCJwYXNzd29yZCI6ImIiLCJlbWFpbCI6ImIiLCJuYW1lIjoiYiIsIl9pZCI6IjU3ZWUyY2I5NjcwZjI3MTMyMTc0MTNiNCJ9LCJfcHJlcyI6eyIkX19vcmlnaW5hbF9zYXZlIjpbbnVsbCxudWxsXSwiJF9fb3JpZ2luYWxfdmFsaWRhdGUiOltudWxsXSwiJF9fb3JpZ2luYWxfcmVtb3ZlIjpbbnVsbF19LCJfcG9zdHMiOnsiJF9fb3JpZ2luYWxfc2F2ZSI6W10sIiRfX29yaWdpbmFsX3ZhbGlkYXRlIjpbXSwiJF9fb3JpZ2luYWxfcmVtb3ZlIjpbXX0sImlhdCI6MTQ3NTIzMDAwNywiZXhwIjoxNDc1MjMxNDQ3fQ.C0LASrYkxaU7FA3EwP8W6NQ85IlLXjdTIKnofeW8YE8","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36","postman-token":"0f3c6b0e-1f63-28ac-2b55-f58bbc209d5c","accept":"*/*","accept-encoding":"gzip, deflate","accept-language":"ja,en-US;q=0.8,en;q=0.6"}
Postman can do it. Besides i succeeded jwt.verify();
I think i'm missing some setting on Swagger, but i can't figure it out, so i'd like to ask advices.
Here is my Swagger codes.
swagger: "2.0"
...
consumes:
- application/json
# format of the responses to the client (Accepts)
produces:
- application/json
paths:
...
/movie:
# our controller name
x-swagger-router-controller: movie
...
post:
description: add a new movie to the list
operationId: save
parameters:
- name: x-access-token
in: header
description: token to be passed as a header
required: true
type: string
...
responses:
...
Thank you for your help.
Oct. 1st 2016
It turned out that codes protecting the root in app.js are working badly.
I created route middleware to protect the route. If i turned it off, i can get the header parameter in the Swagger operationId method.
Apparently, i should consider Swagger Route module such as https://www.npmjs.com/package/swagger-routes.

Related

Why is Safari sometimes, but not always, throwing a cors error when posting to my nodejs API?

I am working as part of a team to design a website where users can either upload an existing video, or record a new video file in-browser. Selecting a file for upload is done with a standard html form, while recording uses react-video-recorder. In either case, once the file is ready, the form is submitted using a ky post request.
const response = await ky.post(`https://xxx.xxx.xxx.xxx:xxxx/upload`,
{
timeout: false,
body: formData,
headers: {
'Authorization': `Bearer ${sessionStorage.getItem('token')}`
}
}).json();
Both methods of adding a file go through this same function, so the headers on the post request will be literally the same regardless of how the user added their video.
Despite this, Safari will throw a cors error only when attempting to upload a video recorded with react-video-recorder. This does not occur when attempting to record and post a video using Chrome for Mac on the same page.
I have checked on the server side, and I am specifically setting the headers to allow the site - I even tried literally copying the "origin" header of the request into the value for "Access-Control-Allow-Origin", just in case I'd made a typo
app.post('/upload',
passport.authenticate('jwt', {session: false}),
function(req,res) {
res.setHeader('Access-Control-Allow-Origin','https://my-website.com')
res.setHeader('Access-Control-Allow-Methods','POST, GET, OPTIONS')
...
At this point, I'm wondering if it's actually a cors issue at all, or if there's something else messed up and Safari is just giving me profoundly unhelpful error messages while I'm troubleshooting. Does anyone have any ideas or tips they can give me?
EDIT: I was able to copy the contents of the http requests, and they are different - I just don't know why...
The successful request is:
POST /upload HTTP/1.1
Accept: application/json
Origin: https://my-website.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryGRcSY52tKpQVBLIb
Authorization: Bearer _redacted
Referer: https://my-website.com/
Content-Length: 51199
Host: my-api.com:3004
Accept-Language: en-ca
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
The failed request:
POST /upload
Authorization: Bearer _redacted
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary0Uzp1dEaDyHuIhEw
Accept: application/json
Origin: https://my-website.com
Referer: https://my-website.com/Upload
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15
Does this indicate that the video file wasn't successfully attached to the post request?

Request blocked if it is sent by node,js axios

I am using axios and a API (cowin api https://apisetu.gov.in/public/marketplace/api/cowin/cowin-public-v2) which has strong kind of protection against the web requests.
When I was getting error 403 on my dev machine (Windows) then, I solve it by just adding a header 'User-Agent'.
When I have deployed it to heroku I am still getting the same error.
const { data } = await axios.get(url, {
headers: {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36',
},
})
Using a fake user-agent in your headers can help with this problem, but there are other variables you may want to consider.
For example, if you are making multiple HTTP requests you may want to have multiple fake user-agents to and then randomize the user-agent for every request made. This can help limit the changes of your scraper being detected.
If that still doesn't work you may want to consider optimizing your headers further. Other than sending HTTP requests with a randomized user-agent, you can further imitate a browser's request Headers by adding more Headers than just the "user-agent"- then ensuring that the user-agent that is selected is consistent with the information sent from the rest of the headers.
You can check out here for more information.
On the site it will not only provide information on how to optimize your headers consistently with the user-agent, but also provide more solutions in case the above mentioned still was unsuccessful.
In my situation, it was the case that I had to bypass cloudflare. You can determine if this is your situation as well if you log your error to the terminal and then check if under the "server" key it says "cloudflare". In which case you can use this documentation for further assistance.

Getting 403 forbidden status through python requests

I am trying to scrape a website content and getting 403 Forbidden status. I have tried solutions like using sessions for cookies and mocking browser through a 'User-Agent' header. Here is the code I have been using
session = requests.Session()
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36',
}
page = session.get('https://www.sizeofficial.nl/product/zwart-new-balance-992/343646_sizenl/', headers = headers)
Note that this approach works on other websites, it is just this one which does not seem to work. I have even tried using other headers which my browser is sending them, and it does not seem to work. Another approach I have tried is to first create a session cookie and then pass that cookie to session.get, still doesn't work for me. Is it not allowed to scrape the website or am I still missing something?
I am using python 3.8 requests to achieve this purpose.

Granting READER role access to a Subscription in Azure works fine in Postman, but not via Angular. Why?

OK, I might be missing something simple here in Angular, but I could really use some help. I am trying to grant a Service Principal READER role to a Subscription programmatically. If I use PostMan, it works fine. However, when I send the same PUT request via Angular6 I get a 400 error from Azure that says:
The content of your request was not valid, and the original object
could not be deserialized. Exception message: 'Required property
'permissions' not found in JSON. Path 'properties', line 1, position
231.'
The JSON being sent in both cases is:
{
"properties":
{
"roleDefinitionId":"/subscriptions/{some_subscription_guid}/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7",
"principalId":"{some_service_provider_guid}"
}
}
I've captured traffic from both requests, and they show as application/json payloads on the PUT. So I am at a loss of what is deserializing incorrectly through Azure that is causing this error. I am trying to follow the REST instructions documented here: https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-rest
Any ideas what I am missing?
UPDATE
Adding the RAW REQUEST per request. I have replaced any sensitive data (access token, GUIDs etc) without changing anything else from the Fiddler output.
PUT https://management.azure.com/subscriptions/<VALID_SUBSCRIPTION_WAS_HERE>/providers/Microsoft.Authorization/roleDefinitions/7ec2aca1-e4f2-4152-aee2-68991e8b48ad?api-version=2015-07-01 HTTP/1.1
Host: management.azure.com
Connection: keep-alive
Content-Length: 233
Accept: application/json, text/plain, */*
Origin: http://localhost:4200
Authorization: Bearer <VALID_TOKEN_WAS_HERE>
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
Content-Type: application/json
Referer: http://localhost:4200/token/<VALID_DOMAIN_WAS_HERE>.onmicrosoft.com/graph
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
{"properties": { "roleDefinitionId":"/subscriptions/<VALID_SUBSCRIPTION_GUID_HERE>/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7", "principalId":"<VALID_OBJECTID_HERE>" }}
Alright, I finally figured out what was going on here. It appears that I was posting to the wrong endpoint. I need to be posting to roleAssignment and not roleDefinitions.
So why did it work in PostMan? It seems there is a fallback from a previous version of the API that supported both when using legacy clients, which for some reason PostMan fell under. However, when posting via Angular it was actively rejecting it.
End result... send to "/Microsoft.Authorization/roleassignments/" with an API version later than "api-version=2015-07-01". All will work.

how to get current windows user from express?

Hi I am new to Nodejs and express framework.
I am implementing a simple CRUD application, and users are expecting to visit the page from MS windows. I wish to log down the current windows user name.
I've tried logging the User-Agent string on the page, and it seems User-Agent does not contain the windows user name. Is this true? and what is the right way to implement this?
res.render('search', {user: req.get('User-Agent')});
Then in jade,
body
p welcome, #{user}!
Here is what i got:
Welcome, Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36!
The User-Agent doesn't include the windows username. Have a look at Wikipedia for further information.
A possible solution to your problem may be a NTLM Authentication. To add this install and optionally save express-ntlm as a dependency:
npm install express-ntlm [--save]
Then require and add it as a middleware to express:
var ntlm = require('express-ntlm');
app.use(ntlm());
You will then be able to use the UserName in jade:
body
p welcome, #{ntlm.UserName}!
In case you want to do a real NTLM Authentication and validate the credentials using an Active Directory you can do this as well:
app.use(ntlm({
domain: 'MYDOMAIN',
domaincontroller: 'ldap://myad.example',
}));

Resources