SharePoint cannot get Access Token with JavaScript? - javascript

I need to get access token from SharePoint, In order to upload some files!
I got access token from postman successfully, But when I try to do the same request with Javascript!
const generateToken = async () => {
const headers = { "Content-Type": "application/x-www-form-urlencoded" };
var formdata = {};
formdata["grant_type"] = "client_credentials";
formdata["client_id"] = "<client_id>";
formdata["client_secret"] = "<client_secret>";
formdata["resource"] =
"00000003-0000-0ff1-ce00-000000000000/site_url#tenant_id";
const body = Object.keys(formdata)
.map((key) => `${key}=${formdata[key]}`)
.join("&");
var requestOptions = {
method: "POST",
headers,
body,
};
await fetch(
"https://accounts.accesscontrol.windows.net/<tenant_id>/tokens/OAuth/2",
requestOptions
)
.then((response) => response.json())
.then((result) => console.log(result))
.catch((error) => console.log("error", error));
};
generateToken();
when I execute the page which have this script I got this error
error TypeError: Failed to fetch
at generateToken
But IDK why the respose status is 200 OK, without returning body which contain access_token
Any help is much appreciated!

You cannot get the token from javascript like that, only from single page applications because of the security issues: you expose your client secret.
You can use Microsoft Authentication Library (MSAL) for JS instead.

Related

Problem returning response from POST request with Axios in Node.js

I am writing a simple post request in a Firebase Cloud function, with Axios. This function calls an API endpoint and gets an object of profile details as response. My problem is to correctly return the response to the client.
In the code below, the Cloud Function logs the result correctly. But I can't figure out how to correctly return it to the client from the client-side callGetProfile() function. (Which runs inside a Vue3 method.)
I am probably missing something obvious but am very new to Node.js and HTPP requests.
Thanks for any help!
// MY FUNCTION IN NODE.JS (Firebase Cloud Functions)
exports.getProfile = functions.https.onCall((data, context) => {
var postData = {
profile_id: "xxxxxxxxxxxxxxxxx", //hardcoded here for testing but should be passed in "data" arg.
profile_type: "personal",
};
let axiosConfig = {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'X-API-KEY': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX'
}
};
axios.post('xxxxxxxxxxxxxxxxxxxxxxxxxxxxx', postData, axiosConfig)
.then((res) => {
console.log(res.data) // this works, I get all the data correctly!!
return res // also tried res.data
})
.catch((err) => {
console.log("AXIOS ERROR: ", err);
})
});
// MY FUNCTION CLIENT SIDE (Vue3 method)
const functions = getFunctions();
const callGetProfile() = httpsCallable(functions, "getProfile");
callGetProfile()
.then((result) => {
console.log(result.data) // this doesn't work, data is "null"
})
.catch((e) => console.log(e));

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?

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

Difference between Python requests POST and axios POST

I am having a difficult time understanding why my API call does not work in axios (relatively new to JS). I have built an API server that takes in an Authorization header with a JWT token.
Here is my POST request workflow in Python:
resp = requests.post('http://127.0.0.1:8000/api/v1/login/access-token', data={'username': 'admin#xyz.com', 'password': 'password'})
token = resp.json()['access_token']
test = requests.post('http://127.0.0.1:8000/api/v1/login/test-token', headers={'Authorization': f'Bearer {token}'})
# ALL SUCCESSFUL
Using axios:
const handleLogin = () => {
const params = new URLSearchParams();
params.append('username', username.value);
params.append('password', password.value);
setError(null);
setLoading(true);
axios.post('http://localhost:8000/api/v1/login/access-token', params).then(response => {
console.log(response)
setLoading(false);
setUserSession(response.data.access_token);
props.history.push('/dashboard');
}).catch(error => {
setLoading(false);
console.log(error.response)
if (error.response.status === 401) {
setError(error.response.data.message);
} else {
setError("Something went wrong. Please try again later.");
}
});
}
// the above works fine
// however:
const [authLoading, setAuthLoading] = useState(true);
useEffect(() => {
const token = getToken();
if (!token) {
return;
}
axios.post(`http://localhost:8000/api/v1/login/test-token`, {
headers: {
'Authorization': 'Bearer ' + token
}
}).then(response => {
// setUserSession(response.data.token);
console.log('we made it')
setAuthLoading(false);
}).catch(error => {
removeUserSession();
setAuthLoading(false);
});
}, []);
if (authLoading && getToken()) {
return <div className="content">Checking Authentication...</div>
}
// RETURNS A 401 Unauthorized response...
What is different about the two above requests? Why does the axios version return different results than requests?
In my API, CORS have been set to *, and I know that the token within Axios is being saved properly in sessionStorage.
Any ideas?
As far as I can see you are passing your username and password in axios as params and as body data in your python request, I am not sure if your backend expects it as params or body data but try changing const params = new URLSearchParams(); to
const params = new FormData(); if the problem is that the backend isn't getting the body data it needs. The best thing I could recommend is checking your browser network tab and seeing what exactly the problem is when you hit your server.

Spring MVC with Reactjs fetch error

I am getting a similar error from (here)[Getting "TypeError: failed to fetch" when the request hasn't actually failed
My method is annotated with #CrossOrigin
With postman my request works fine ( from locally)
see POST to http://star-is.info:8080/app-1.0.0-BUILD-SNAPSHOT/register with headers Content-Type application/x-www-form-urlencoded and passing a string with firstname
Locally works fine but my form (here)[http://star-is.info:8082/] does not
const data = {};
data['firstname'] = this.state.firstname;
console.log('submitSignup');
fetch('http://localhost:8080/app-1.0.0-BUILD-SNAPSHOT/register', {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then((response) => response.json()
.catch(err => {
console.err(`'${err}' happened!`);
return {};
})).then(function (body) {
console.log(body);
})
.catch(error => {
alert(error);
});
Now I am getting a reply from server
{firstname: null}
but why is firstname not being passed to the server..
The way i achieved this much as using register as endpoint to call in fetch
and using proxy in package.json
I removed JSON.stringify with the data and still it is null
See with postman I get the same string back
I even tried this
const data = {'firstname' : this.state.firstname};
it is still returned null
Finally it works. I had to encode the data being sent. Is there a better way to do this in Reactjs for more complex objects
const searchParams = Object.keys(data).map((key) => { return encodeURIComponent(key) + '=' + encodeURIComponent(data[key]); }).join('&');
And then use searchParams in the body of fetch

Categories