Django OAuth Toolkit and POSTMAN - django

I made a django OAuth server using Django OAuth Toolkit.
I've setup the code right and when I use CURL in the following way:
curl -X POST -d "grant_type=password&username=geethpw&password=abcabcabc" -u"wHsGgpsHZyw8ghnWbEPZC8f4AZLgJIPmoo50oNWp:ZQcXeQWnae0gmX0SMi6Xn6puBnhiphR2M80UC6ugmffbrUd66awhbguYgxtQ1ufahJZehj4RlGjYu06fHkVgO15TURttSozj27nshl0AhFfCVzUKqTDubBimTSsK4yDS" http://localhost:8000/o/token/
I get a response:
{"access_token": "glzwHLQNvUNQSOU5kFAoopgJxiNHcW", "token_type": "Bearer", "expires_in": 36000, "refresh_token": "5k6jvCd2UxaRUGHKONC2SqDukitG5Y", "scope": "read write groups"}Geeths-MacBook-Pro:~ geethwijewickrama$
Geeths-MacBook-Pro:~ geethwijewickrama$
which is expected.
But When I try postman to do the samething, I always get:
{
"error": "unsupported_grant_type"
}
My headers are:
Content-Type:application/x-www-form-urlencoded
If I remove this header I get:
{
"error": "invalid_client"
}
How can I test my APIs in postman?

Your postman body should be something like:
grant_type: <grant_type>
client_id: <client_id>
client_secret: <client_secret>
username: <username>
password: <password>
Try Bulkedit with these, hope this helps (Hope you have registered the app to obtain client_id and client_secret)

Get token from django-oauth-toolkit from JS:
async function getToken () {
let res = await fetch("https://<your_domain>/o/token/", {
body: new URLSearchParams({
grant_type: 'password',
username: '<user_name>',
password: '<user_pass>',
client_id: '<client_app_id>',
client_secret: '<client_pass>'
}),
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
method: "POST"
})
return res.json();
}
console.log(await getToken());
Your client application authorisation grant type should be: "Resource owner password-based"
P.S. I've failed to get token via "Content-Type": "application/json", not sure why (django-oauth-toolkit documentation says nothing about that).

Related

How to authenticate through Google Cloud IAP with client from gapi (google-api-javascript-client) library?

Given a client-side app (written in Angular, but it's not much important) where I use google-api-javascript-client library to authenticate users. In a way described here - https://developers.google.com/sheets/api/quickstart/js:
gapi.load('client:auth2', () => {
gapi.client.init({
clientId: CLIENT_ID,
scope: SCOPES,
discoveryDocs: DISCOVERY_DOCS
}).then(() => {
gapi.auth2.getAuthInstance().isSignedIn.listen(this.onSigninStatusChanged.bind(this));
const isSignedIn = gapi.auth2.getAuthInstance().isSignedIn.get();
if (!isSignedIn) {
gapi.auth2.getAuthInstance().signIn({prompt: 'select_account'});
}
});
});
Now I want to access a backend in AppEngine behind Identity-Aware Proxy (IAP).
I tried naively to pass a token from GoogleUser via http request's authorization header, but it doesn't seem to work (getting 401):
let token = gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse().id_token;
this.http.get<Config>('https://myservice-dot-myproject.ew.r.appspot.com/api/get',
{
headers: { 'Authorization': 'Bearer ' + token}
});
I guess I need somehow to use OAuth Client ID from IAP.
I found a sample on how to do it with nodejs auth client.
But can't find a way to do it with the client-side google-api-javascript-client lib.
UPDATE:
I found a nice online resource to verify token that I got from GoogleUser.getAuthResponse().id_token - https://oauth2.googleapis.com/tokeninfo?id_token=token (source), it display the following:
{
"iss": "accounts.google.com",
"azp": "my OAuth Client ID that I used in gapi (CLIENT_ID)",
"aud": "OAuth Client ID that I used in gapi (CLIENT_ID)",
"sub": "user id (number)",
"hd": "Google user GSuite domain",
"email": "Google user email",
"email_verified": "true",
"at_hash": "some hash",
"name": "Google user name",
"picture": "an url",
"given_name": "Google user firstname",
"family_name": "Google user lastname
"locale": "en",
"iat": "1615972232",
"exp": "1615975832",
"jti": "87129b6c0f684b0bc7beac9df5e522e6272c13f1",
"alg": "RS256",
"kid": "6a8ba5652a7044121d4fedac8f14d14c54e4895b",
"typ": "JWT"
}

GCIP - enable authorization code grant flow using OIDC based external provider

Trying to configure GCIP with Salesforce Identity as IDP. Tried configuring OIDC based integration. Noticed that there is no field for providing (sfdc) client secret for OIDC based configuration. Also, the response_type=id_token is getting invoked from GCIP side. We want to use authorization code flow (response_type=code) to integrate with SFDC. Is it possible?
Code flow for OIDC providers is supported on the GCIP backend. It is just not yet exposed in the Cloud Console or the Admin SDKs.
Notice it is documented here in the REST API.
You will need to set {code: true}
Here is a snippet in Node.js (untested):
// https://cloud.google.com/identity-platform/docs/reference/rest/v2/projects.oauthIdpConfigs/patch
return new Promise((resolve, reject) => {
request({
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
url: `https://identitytoolkit.googleapis.com/admin/v2/projects` +
`/${projectId}/oauthIdpConfigs/${oidcProviderId}?updateMask=responseType`,
method: 'PATCH',
body: JSON.stringify({
responseType: {
idToken: true,
code: true,
}
}),
}, (error, response) => {
if (!error && response.statusCode === 200) {
resolve();
} else {
reject(error);
}
});
});
});

I have an app with react as frontend and django rest framework as backend, i use axios to send my response, but the data is empty

I have an app with react and Django rest framework. I use Django allauth for login and registration. when I want to log in, everything is ok, and the response is 201 but the data is empty and I don't get token. I send this request with the postman and I get the token. what should i do?
React Request:
axios({
method: 'post',
url: 'http://localhost:8000/rest-auth/login/',
data: {
username: 'admin',
email: '',
password: 'admin123456'
},
headers: { 'content-type': 'application/json' }
})
.then(response => {
console.log(response.data.key);
})
.catch(error => {
console.log(error);
});
the response is:
{data: "", status: 200, statusText: "OK", headers: {…}, config: {…}, …}
postman request: http://localhost:8000/rest-auth/login/
{
"username": "mahtab",
"email": "",
"password": "mahtab23"
}
postman response:
{
"key": "f75b9f54848a94ac04f455321118aff5d5a7e6f8"
}

"error": "invalid_client" django-oauth-toolkit

I am using django rest framework with django-oauth-toolkit. When i request access token on my localhost it gives me the access token as shown below
~/django_app$ curl -X POST -d "grant_type=password&username=<Your-username>&password=<your-password>" -u"<client-id>:<client-secret>" http://localhost:8000/o/token/
{"access_token": "8u92BMmeZxvto244CE0eNHdLYWhWSa", "expires_in": 36000, "refresh_token": "faW06KKK71ZN74bx32KchMXGn8yjpV", "scope": "read write", "token_type": "Bearer"}
But when i request the access token from the same project hosted on live server, it give me error as invalid_client.
~/django_app$ curl -X POST -d "grant_type=password&username=<Your-username>&password=<your-password>" -u"<client-id>:<client-secret>" http://<your-domain>/o/token/
{
"error": "invalid_client"
}
I am not able to understand where is the problem coming from. I have searched a lot and didn't find the right answer. Please advise me what to do to get rid of this error.
I found the solution for this, instead of grant_type=password i have used grant_type=client_credentials then i got the access token. You can see the curl command below.
curl -X POST -d "grant_type=client_credentials&client_id=<your-client id>client_secret=<your-client secret>" http://your-domain/o/token/
{"scope": "read write", "token_type": "Bearer", "expires_in": 36000, "access_token": "ITx5KCjupsdbvbKvNQFyqZDEw6svSHSfdgjh"}
OR
If you want to do it with grant-type=password then here is command for that:
curl -X POST -d "grant_type=password&username=<your-username>&password=<your-password>&client_id=<your-client id>&client_secret=<your-client secret>" http://your-domain/o/token/
{"access_token": "0BVfgujhdglxC7OHFh0we7gprlfr1Xk", "scope": "read write", "token_type": "Bearer", "expires_in": 36000, "refresh_token": "AwffMPzNXvghlkjhs8dpXk7gbhhjhljlldfE2nI"}
I referred this https://developer.amazon.com/de/docs/adm/request-access-token.html as my application was on AWS.
Get token from django-oauth-toolkit in JavaScript:
async function getToken () {
let res = await fetch("https://<your_domain>/o/token/", {
body: new URLSearchParams({
grant_type: 'password',
username: '<user_name>',
password: '<user_pass>',
client_id: '<client_app_id>',
client_secret: '<client_pass>'
}),
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
method: "POST"
})
return res.json();
}
console.log(await getToken());
Your client application authorisation grant type should be: "Resource owner password-based"
P.S. I've failed to get token via "Content-Type": "application/json", not sure why (django-oauth-toolkit documentation says nothing about that).

React + Django Axios Issues

I have a react application linked to a Django backend on two separate servers. I am using DRF for django and I allowed cors using django-cors-headers. For some reason when I curl POST the backend, I am able to get the request out. However when I use axios POST the backend, I get and error. The status of the POST request from axios is failed. The request and takes more than 10 seconds to complete. My code was working locally (both react and django codes), but when I deployed to AWS ec2 ubuntu, the axios requests stopped working.
Console error logs
OPTIONS http://10.0.3.98:8000/token-auth/ net::ERR_CONNECTION_TIMED_OUT
{
"config": {
"transformRequest": {},
"transformResponse": {},
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"headers": {
"Accept": "application/json, text/plain, */*",
"Content-Type": "application/json;charset=UTF-8",
"Access-Control-Allow-Origin": "*"
},
"method": "post",
"url": "http://10.0.3.98:8000/token-auth/",
"data": "{\"username\":\"testaccount\",\"password\":\"testpassword\"}"
},
"request": {}
}
Here is my request code
axios.post('http://10.0.3.98:8000/token-auth/',
JSON.stringify(data),
{
mode: 'no-cors',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin' : '*'
},
},
).then( res => (
console.log(JSON.stringify(res)),
)
).catch( err => (
console.log(JSON.stringify(err))
)
);
my curl code that worked
curl -d '{"username":"testaccount", "password":"testpassword"}' -H "Content-Type: application/json" -X POST http://10.0.3.98:8000/token-auth/
UPDATE 1
on firefox i am getting the warning
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at http://10.0.3.98:8000/token-auth/. (Reason:
CORS request did not succeed).[Learn More]
UPDATE 2
Perhaps it has something to do with my AWS VPC and subnets? My django server is in a private subnet while my react app is in a public subnet.
UPDATE 3 - my idea of what the problem is
I think the reason why my requests from axios aren't working is because the requests i'm making is setting the origin of the request header to http://18.207.204.70:3000 - the public/external ip address - instead of the private/internal ip address which is http://10.0.2.219:3000 - i search online that the origin is a forbidden field so it can't be changed. How can i set the origin then? Do I have to use a proxy - how can I do that.
try this http request instead of axios, it's called superagent (https://www.npmjs.com/package/superagent) , just install it to your react app via npm,
npm i superagent
and use this instead of axios.
import request from 'superagent'
const payload ={
"1": this.state.number,
"2": this.state.message
}
request.post('LINK HERE')
.set('Content-Type', 'application/x-www-form-urlencoded')
.send(payload)
.end(function(err, res){
if (res.text==='success'){
this.setState({
msgAlert: 'Message Sent!',
})
}
else{
console.log('message failed/error')
}
});
The issue here is that the request is being made on the client browser. You need to either use a reverse proxy or request directly to the api server. You cannot do a local ssh forwarding either.