Fetch call returning 401: Unauthorized - javascript

I am attempting to fetch a php app hosted on AWS with basic authentication. I followed tutorials and attempted other answers such as encrypting the username and password using btoa
Currently, this is my code:
let h = new Headers();
let url = "URL"
let user = "USER"
let pass = "PASS"
let encoded = window.btoa(`${user}:${pass}` )
let auth = ('Basic ' + encoded)
console.log(auth)
h.append('Authorization', auth)
console.log(h.has('Authorization'))
fetch(url, {
headers: h
}) .then(res => console.log(res))
Thanks in advance!

Related

Discord API - Not allowed to request source

I am trying to make „Login with Discord“ (OAuth) using Discords Api. I need the users ID, the Name and the role of the member in the guild.
It fails to fetch the source after I got redirected from the OAuth Page:
My JS for that page:
window.onload = () => {
const fragment = new URLSearchParams(window.location.hash.slice(1));
const [accessToken, tokenType] = [fragment.get('access_token'), fragment.get('token_type')];
fetch('http://discord.com/api/guilds/874613987487121408/members/491553591434412057', {
headers: {
authorization: `${tokenType} ${accessToken}`,
},
})
.then(result => result.json())
.then(response => {
const username = response.user;
const roles = response.roles;
document.getElementById('info').innerText += username + roles;
})
.catch(console.error);
};
However, it gets me an error message: Not allowed to request source.
Can someone help me?

Making my own API, confused on how to authenticate with server

I'm trying to make a Discord bot that retrieves a player's stats from the Ubisoft Rainbow Six stat website. I've worked with APIs before and I know the basics of Node and making GET requests to certain URLs. I monitored the network activity for a player's profile and found the specific URL that I need to perform a request on but I get a HTTP 400 error. I'm assuming this is because I've never authenticated with the server who I am. So I read up on authentication and the like and figured that all I had to do was include in the request header my username and password for the website(at this point I should mention that the site makes you login to retrieve player's stats). I went on Postman and included my username/password for Basic Auth and OAuth2 and I still get a HTTP 400 error, so there's obviously got to be more that I'm missing. It seems that in the network activity that some of the requests include a token, which I'm assuming is some sort of session token. I'm just completely confused as to what I'm supposed to do, as I'm kind of diving head first into this but I would really appreciate it if someone could provide some resources where I could try to fill in the gaps or help me resolve the issue. Code at the moment using pure JS/Node:
//import
const https = require('https');
const http = require('http');
//https://public-ubiservices.ubi.com/v3/profiles?namesOnPlatform=pope&platformType=uplay
var username = '';
var password = '';
var req_username = '';
//get session_id
function get_session_id(username, password) {
const options = {
host: 'public-ubiservices.ubi.com',
port: 443,
path: '/v3/profiles/sessions',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic' + Buffer.from(username + ':' + password).toString('base64'),
'Ubi-AppId': '',
}
}
const req_session_id = https.request(options, res => {
let res_body = '';
res.on('data', data => {
res_body += data;
})
res.on('end', () => {
res_body = JSON.parse(res_body);
console.log(res_body);
})
});
req_session_id.end();
}
//retrieve player stats
function get_stats(req_username) {
const options = {
host: 'public-ubiservices.ubi.com',
port: 443,
path: `/v3/profiles?namesOnPlatform=${req_username}&platformType=uplay`,
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic' + Buffer.from(username + ':' + password).toString('base64'),
'Ubi-AppId': '',
}
}
const req_get_stats = https.request(options, res => {
let res_body = '';
res.on('data', data => {
res_body += data;
});
res.on('end', () => {
res_body = JSON.parse(res_body);
console.log(res_body);
});
});
req_get_stats.end();
}
get_session_id(username, password);
get_stats(req_username);
try this out:
https://www.npmjs.com/package/r6api.js
heres an example:
const R6API = require('r6api.js');
const r6api = new R6API('email', 'password');
const username = 'Daniel.Nt'
const platform = 'uplay';
const id = await r6api.getId(platform, username).then(el => el[0].userId);
const stats = await r6api.getStats(platform, id).then(el => el[0]);
console.log(`${username} has played ${stats.pvp.general.matches} matches.`);

Fetch with Credentials JS

I am trying to call fetch with credentials to hit a https api
url: https://{apikey}:{password}#{hostname}/admin/api/{version}/{resource}.json
I try this:
var apikey = "mykey";
var password = "mypass";
var hostname = "myhost";
var version = "version";
var resource = "resource";
var API_URL = `https://${apikey}:${password}#${hostname}/admin/api/${version}/${resource}.json`;
fetch(API_URL, {
credentials: "omit"
})
.then((response) => response.json())
.then((data) => console.log(data));
but return this error:
Failed to execute 'fetch' on 'Window': Request cannot be constructed from a URL that includes credentials
Just send credential with Header Authorization Bearer or Basic with base64 encoded credentials

Call an URL with Auth Token with Fetch API

I'm using the Fetch API to Login to my Webapp using Baisc Authentication. After a successful login the server returns a token as a json object. I am then using this token to make requests to other API Endpoints. Those endpoints just show a webpage if the request contains a valid token.
Everything works fine but nothing shows up in the browser after I make a successful call with the fetch API..
If I call the API endpoint in a REST Client it returns the html which seems to be fine. The problem seems to be that the browser should call the url instead of just fetch the html..
Here is my code. I am getting the "Success"-Alert - so everything seems to work fine. But I need the browser to show the result as a new page (some kind of a direct call of the url with the token in the header).
function login(event) {
event.preventDefault();
let username = document.getElementById("username").value;
let password = document.getElementById("password").value;
let url = URL + 'login';
let headers = new Headers();
headers.append('Authorization', 'Basic ' + btoa(username + ":" + password));
fetch(url, {method:'GET',
headers: headers,
})
.then(function(response)
{
if (response.ok) {
return response.json();
} else {
let error = document.getElementById("login-error");
error.innerHTML = "Username/Password incorrect.";
}
})
.then(function(json)
{
if (typeof(json) !== "undefined") {
startWebapp(json.token);
}
})
.catch(error => console.error('Error:', error));
}
function startWebapp(token) {
let url = URL + 'webapp/overview';
let headers = new Headers();
headers.append('Authorization', 'Bearer ' + token);
fetch(url, {method:'GET',
headers: headers,
})
.then(function(response) {
alert("Success!");
return response;
});
}
How can I achieve that the browser actually calls the url with the API token and opens it if the fetch is successful?
For anyone searching for a solution:
This is actually not possible with JavaScript nor the fetch API. For me the (easiest) solution is to save the token in a cookie. The server then searches for a token in the cookie and uses it for authentication/authorization. This works pretty well and I don't need to send the token on every request.
Hope that helps.

using twitter api to get token

I am trying to use the twitter api, but need to get authentication. There are 2 types , and I only need Application-only authentication aka app only. This is the type of authentication where an application makes API requests on its own behalf.
The docs explain to use this method, you need to use a bearer token. You can generate a bearer token by passing your consumer key and secret through the POST oauth2 / token endpoint.
Here is the link to docs explaining this endpoint. There is even an example request but still it isn't very clear to me what needs to be done.
I have an API key and API secret key, but am getting the following error:
body: ‘{“errors”:[{“code”:170,“message”:“Missing required parameter:
grant_type”,“label”:“forbidden_missing_parameter”}]}’ }
My server side code looks like this
var request = require('request');
var btoa = require('btoa');
const KEY = encodeURIComponent('1234');
const SECRET = encodeURIComponent('5678');
request({
headers: {
'Authorization': 'Basic ' + btoa(`${KEY}:${SECRET}`),
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
uri: 'https://api.twitter.com/oauth2/token',
method: 'POST',
body: JSON.stringify({
'grant_type': 'client_credentials' // I am passing the grant_type here
})
}, function (err, res, body) {
console.log('res', res)
});
The CURL request in the docs looks like the following:
POST /oauth2/token HTTP/1.1
Host: api.twitter.com
User-Agent: My Twitter App v1.0.23
Authorization: Basic eHZ6MWV2R ... o4OERSZHlPZw==
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
Content-Length: 29
Accept-Encoding: gzip
grant_type=client_credentials
To to this there were a couple of things. First the request needed to be made server side. You need to install btoa from npm to provide the encoding of the key and secret key. The KEY and SECRET need to be separated by a colon. The body of the request needs to be a string of
'grant_type=client_credentials'
See full code example below.
const btoa = require('btoa');
request({
headers: {
'Authorization': 'Basic ' + btoa(`${KEY}:${SECRET}`),
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
uri: 'https://api.twitter.com/oauth2/token',
method: 'POST',
body: 'grant_type=client_credentials'
}, (error, response, body) => {
const token = JSON.parse(body).access_token;
});
For Swift 5
let configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration)
let info = Bundle.main.infoDictionary
let twitterConsumerKey : String = (info?["TwitterConsumerKey"] as? String)!
let twitterConsumerSecret : String = (info?["TwitterConsumerSecret"] as? String)!
let loginString = String(format: "%#:%#", twitterConsumerKey, twitterConsumerSecret)
let loginData = loginString.data(using: String.Encoding.utf8)!
let base64LoginString = loginData.base64EncodedString()
let urlString = NSString(format: "https://api.twitter.com/oauth2/token");
print("url string is \(urlString)")
let request : NSMutableURLRequest = NSMutableURLRequest()
request.url = NSURL(string: NSString(format: "%#", urlString)as String) as URL?
request.httpMethod = "POST"
request.timeoutInterval = 30
request.httpBody = "grant_type=client_credentials".data(using: String.Encoding.utf8)!
request.addValue("application/x-www-form-urlencoded;charset=UTF-8", forHTTPHeaderField: "Content-Type")
request.addValue("Basic \(base64LoginString)", forHTTPHeaderField: "Authorization")
let dataTask = session.dataTask(with: request as URLRequest) {data, response, error -> Void in
guard let httpResponse = response as? HTTPURLResponse,
let receivedData = data else {
print("error: not a valid http response")
return
}
switch (httpResponse.statusCode)
{
case 200:
let response = NSString (data: receivedData, encoding: String.Encoding.utf8.rawValue)
if response == "SUCCESS"
{
}
default:
print("save profile POST request got response \(httpResponse.statusCode)")
let str = String(decoding:data!, as: UTF8.self)
print(str)
}
}
dataTask.resume()
The problem is with the format of http body of request. I was wrongly using dictionary of grant_type : client_credentials instead of string grant_type= client_credentials.
request.httpBody = try! JSONSerialization.data(withJSONObject:
["grant_type" : "client_credentials"], options: [])

Categories