django-oauth-toolkit 'invalid client' error after deploy on AWS Elasticbeanstalk - django

I use django-oauth-toolkit with my django/django-rest-framework application. When I request an access token in dev mode on localhost, it works OK:
dev#devComp:$ curl -X POST -d "grant_type=password&username=
<user_name>&password=<password>" -u"<client_id>:<client_secret>"
http://localhost:8000/o/token/
{"access_token": "fFySxhVjOroIJkD0IuEXr5WIhwdXg6", "expires_in":
36000, "token_type": "Bearer", "scope": "read write groups",
"refresh_token": "14vhyaCZbdLtu7sq8gTcFpm3ro9YxH"}
But if I request an access token from absolutely the same application deployed at AWS Elasticbeanstalk, I get 'invalid client' error:
dev#devComp:$ curl -X POST -d "grant_type=password&username=
<user_name>&password=<password>" -u"<client_id>:<client_secret>"
http://my-eb-prefix.us-west-1.elasticbeanstalk.com/o/token/
{"error": "invalid_client"}
Please advise me what to do to get rid of this error and normally request access tokens from django app deployed at AWS.

After some research, I can now give the answer myself:
I had to add one more command to my python.config in .ebextensions folder:
...
container_commands:
...
03wsgipass:
command: 'echo "WSGIPassAuthorization On" >> ../wsgi.conf'
After that, AWS allows incoming requests to pass authorization, and I get the response without an error.

I was also facing the same problem.
This worked for me:
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"}

Related

POST, PUT and PATCH resources not working in WSO2 Api Gateway

I am quite new to the WSO2 tools. I recently started using the WSO2 API Manager(ver. 3.1.0).
I created an API gateway by importing the httpbin swagger specs: https://github.com/Azure/api-management-samples/blob/master/apis/httpbin.swagger.json. I published the API, subscribed to it, generated the API keys and started testing.
I imported the spec in Postman, configured the API key for authorization, changed the server to the local gateway http://localhost:8280/Api_Base/1.0
All the resources defined with GET method were accessible, but the POST, PUT and PATCH resources
were not reachable via the gateway. I received the following error response "<faultstring>unknown" for these resources. I tried with cURL as well but got the same results. When I tried POST for httpbin directly it was working just fine:
curl --location --request POST 'http://httpbin.org/post'
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"User-Agent": "curl/7.58.0",
"X-Amzn-Trace-Id": "Root=1-5e8e0d39-ddf21f1055008f60707cf150"
},
"json": null,
"origin": "95.103.xxx.xxx",
"url": "http://httpbin.org/post"
}
and via my API gateway(with API key as well):
curl --location --request POST 'http://localhost:8280/HTTP_Bin_Mock/1.0/post'
<faultstring>unknown</faultstring>
What could have gone wrong?
please try below CURL command
curl --location --request POST 'http://localhost:8280/HTTP_Bin_Mock/1.0/post' --data '{}' --header 'Content-Type: Application/JSON'

Why did my POST to AWS API Gateway failed?

I use POSTMAN to test my Cloudformation created APIs
POST https://6pppnxxxh.execute-api.eu-central-1.amazonaws.com/Prod/users
I got
{
"message": "Missing Authentication Token"
}
My prod stage
I doublechecked PROD Invoke URL.
How to solve this problem?
I tried with curl
curl --header "Content-Type: application/json" --request POST --data '{ "emailaddress" : "acj#rambler.ru,"first name" : "Aca","last name" : "Ljubascikic", "password" : "bbbac_96"}' https://6pppnxxxh.execute-api.eu-central-1.amazonaws.com/Prod/users
The same issue
{"message":"Missing Authentication Token"}
How to test from CLI?
According to your screenshot /Prod/users is a PUT method and you are using POST in your command. I would confirm that first.
Hope this helps.

AWS - Cognito Authentication - Curl Call - Generate Token Without CLI - No Client Secret

I have created a API Gateway and I have applied Cognito Authentication there. Here to have the API Call work I am using AWS CLI to get Token , Here is my CLI Code
aws cognito-idp admin-initiate-auth --user-pool-id us-west-2_leb660O8L --client-id 1uk3tddpmp6olkpgo32q5sd665 --auth-flow ADMIN_NO_SRP_AUTH --auth-parameters USERNAME=myusername,PASSWORD=mypassword
Now I want to use CURL Call instead of this CLI Call. I have found the code but all needs client secret here. I do not have client secret as my user pool is of Enable Signin for server-based authentication.
Please guide me how I can use that.
I have gone through
https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html
[What will be the EndPoint for Calling IntiateAuth Or AdminIntiateAuth]
&
https://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html
To Summarise this :
I want to get Id_Token Using Curl or Postman without Client Secret.
Thanks in advance
You can authenticate a user with the following request.
This is the endpoint of the InitiateAuth request.
Hope that this is useful for you
Method: POST
Endpoint: https://cognito-idp.{REGION}.amazonaws.com/
Content-Type: application/x-amz-json-1.1
X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth
Body:
{
"AuthParameters" : {
"USERNAME" : "YOUR_USERNAME",
"PASSWORD" : "YOUR_PASSWORD"
},
"AuthFlow" : "USER_PASSWORD_AUTH", // Don't have to change this if you are using password auth
"ClientId" : "APP_CLIENT_ID"
}
And the response as the following
{
"AuthenticationResult": {
"AccessToken": "YOUR_ACCESS_TOKEN",
"ExpiresIn": 3600,
"IdToken": "YOUR_ID_TOKEN",
"RefreshToken": "YOUR_REFRESH_TOKEN",
"TokenType": "Bearer"
},
"ChallengeParameters": {}
}
Just sharing direct curl here may helpful to anyone
curl -X POST --data #user-data.json \
-H 'X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth' \
-H 'Content-Type: application/x-amz-json-1.1' \
https://cognito-idp.<just-replace-region>.amazonaws.com/
file json user-data.json
{"AuthParameters" : {"USERNAME" : "sadfsf", "PASSWORD" : "password"}, "AuthFlow" : "USER_PASSWORD_AUTH", "ClientId" : "csdfhripnv7sq027kktf75"}
make sure your app client does not contain app-secret or create new app without secret. also inside app enable USER_PASSWORD_AUTH

"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).

number of instances the cloud foundry app is running

my app needs to get the number of instances in which its running, (in runtime my app uses this info in my program logic).
(VCAP_APPLICATION env variables cannot provide this info. )
Calling API directly and using "instances" attribute is an option, but I dont know how to call apps API directly in my app. Please let me know how to call it.
Below is the link I got for app API:
http://apidocs.cloudfoundry.org/218/apps/retrieve_a_particular_app.html
In order to use the API, you first need to authenticate. In order to authenticate, you need to retrieve the authorization endpoint.
To retrieve the authorization endpoint, issue the following curl request (I am using pivotal web services in this example, but you would replace https://api.run.pivotal.io with the cloud foundry api endpoint you are using.
curl -H 'content-type: application/x-www-form-urlencoded;charset=utf-8' \
-H 'accept: application/json;charset=utf-8' \
https://api.run.pivotal.io/v2/info
You'll get back something that looks like this:
{
"name": "vcap",
"build": "2222",
"support": "http://support.cloudfoundry.com",
"version": 2,
"description": "Cloud Foundry sponsored by Pivotal",
"authorization_endpoint": "https://login.run.pivotal.io",
"token_endpoint": "https://uaa.run.pivotal.io",
"min_cli_version": null,
"min_recommended_cli_version": null,
"api_version": "2.36.0",
"app_ssh_endpoint": "ssh.run.pivotal.io:2222",
"app_ssh_host_key_fingerprint": "e7:13:4e:32:ee:39:62:df:54:41:d7:f7:8b:b2:a7:6b",
"logging_endpoint": "wss://loggregator.run.pivotal.io:443",
"doppler_logging_endpoint": "wss://doppler.run.pivotal.io:443"
}
Grab the authorization_endpoint value, in this case it is:
https://login.run.pivotal.io
You now need to grab an authentication token. Issue the following curl command replacing the [my user name] and [my password] and [my authorization endpoint] with your values. Please note that you should url encode your password.
curl -H 'content-type: application/x-www-form-urlencoded;charset=utf-8' \
-H 'accept: application/json;charset=utf-8' \
-H 'authorization: Basic Y2Y6' \
-d "username=[my user name]&password=[my password]&grant_type=password" \
[my authorization endpoint]/oauth/token
You will get a response that looks like this:
{
"access_token": "very_long_token.very_long_token.very_long_token",
"token_type": "bearer",
"refresh_token": "very_long_token.very_long_token.very_long_token",
"expires_in": 599,
"scope": "cloud_controller.read password.write cloud_controller.write openid",
"jti": "shorter_value"
}
You are interested in the access_token value (access_token, refresh_token, and jti have been changed from the actual values in this example)
Now we are finally at the point where we can use the api to get the information about our app. You could use the link you provided above, but to use that api endpoint, you need the guid of your app. Instead I would recommend using the List all Apps endpoint and use a query filter on it to get your app information. Here is the curl command (replace [my authorization token] with your auth token from the previous step, replace [my api endpoint] with the api endpoint you use for cloud foundry, replace [my app name] with the name of your app:
curl -H "authorization: bearer [my authorization token]" \
[my api endpoint]/v2/apps?q=name:[my app name] -X GET
You'll receive a message that looks like this:
{
"total_results": 1,
"total_pages": 1,
"prev_url": null,
"next_url": null,
"resources": [
{
"metadata": {
"guid": "blah-blah",
"url": "/v2/apps/blah-blah",
"created_at": "time_stamp",
"updated_at": null
},
"entity": {
"name": "my-app",
"production": false,
"space_guid": "blah-blah",
"stack_guid": "blah-blah",
"buildpack": null,
"detected_buildpack": null,
"environment_json": {
},
"memory": 1024,
"instances": 3,
"disk_quota": 1024,
"state": "STOPPED",
"version": "blah-blah",
"command": null,
"console": false,
"debug": null,
"staging_task_id": null,
"package_state": "STAGED",
"health_check_type": "port",
"health_check_timeout": null,
"staging_failed_reason": null,
"staging_failed_description": null,
"diego": false,
"docker_image": null,
"package_updated_at": "time stamp",
"detected_start_command": "",
"enable_ssh": true,
"docker_credentials_json": {
"redacted_message": "[PRIVATE DATA HIDDEN]"
},
"space_url": "/v2/spaces/blah-blah",
"stack_url": "/v2/stacks/blah-blah",
"events_url": "/v2/apps/blah-blah/events",
"service_bindings_url": "/v2/apps/blah-blah/service_bindings",
"routes_url": "/v2/apps/blah-blah/routes"
}
}
]
}
You can grab the instances from the message. If you want to use the api in your original link, you can grab the metadata.guid for use in that call.
Hope that helps!
I was looking for something similar but using cf cli, to get the instance count of my app in a shell script. I came up with this and it works.
cf app my_app_name|grep instances|cut -d'/' -f2
I understand this post might not be related, but i would be happy if it helps someone.
Though it is late now to reply - an alternate solution would be to have a service discovery component like Eureka and let your application register to it. From the discovery client, you can get the number of instances for this application.
Be aware though, the state of instances would be eventually consistent on Eureka. We are using this pattern for a cluster broadcast use case.
create a container to container link with the name myapp.apps.internal. Then count the IP's returned by a DNS lookup of myapp.apps.internal.