Invalid Client with paypal api, client authentication failed using HTTPoison.post!/3 - api

I am using HTTPoison to send request to the Paypal api. Here is the paypal documentation for using its api for logging in: https://developer.paypal.com/docs/log-in-with-paypal/integrate/
When I get the code, and try to exchange it for an access token, I get this error: "{\"error\":\"invalid_client\",\"error_description\":\"Client Authentication failed\"}",
Here is how HTTPoison.post!/3 post request:
url = "https://api-m.sandbox.paypal.com/v1/oauth2/token"
headers = [
Authorization: "Basic #{ClientID}:#{Secret}"
]
body = "grant_type=authorization_code&code=#{code}"
HTTPoison.post!(url, body, headers)
This shows the a status_code: 401 and {\"error\":\"invalid_client\",\"error_description\":\"Client Authentication failed\"}", error.. How can this issue be solved?

HTTP Basic Authentication requires the value to be base-64 encoded. Try doing that:
Authorization: "Basic " <> Base.encode64("#{ClientID}:#{Secret}")

Related

OAuth2: Unable to Authenticate API request

Been tasked to export forms and items from Podio using the API. Trying to do this with straight Python and Requests instead of the canned API tool. Am successful at retrieving the access and refresh tokens, but am unable to make the simplest Get request. The response has the error:
"error_description":"Authentication as None is not allowed for this method"
Tried this with 2 versions of using OAuth2 in Requests, both return that response.
What is it trying to tell me? Aside from giving the token, is there any other authentication attributes required?
client = BackendApplicationClient(client_id=CLIENT_ID)
oauth = OAuth2Session(client=client)
token = oauth.fetch_token(token_url=auth_url, client_id=CLIENT_ID,
client_secret=CLIENT_SECRET)
print('token:', token)
access_token = token["access_token"]
api_url = base_url + 'user/status'
r = oauth.get(api_url)
print(r.text)
headers = {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
"Authorization": "Bearer " + token["access_token"]}
response = requests.get(api_url, headers=headers, verify=True)
print(response.text)
Here is full response:
{"error_parameters":{},"error_detail":null,"error_propagate":false,"request":{"url":"http://api.podio.com/user/status","query_string":"","method":"GET"},"error_description":"Authentication as None is not allowed for this method","error":"forbidden"}

Cannot POST request using service account key file in Python, getting 'Invalid IAP credentials: Unable to parse JWT', '401 Status Code'

I am trying to send a POST request to a Google App Engine service with a JSON body accompanied by an authorization token. I am generating the access token from a local service account key JSON file. The code below is generating a credential but finally the authorization is being rejected. I also tried different ways already. Even tried writing the request in Postman with a Bearer token in the Header, or even as a plain cURL command. But whatever I try, getting a 401 authentication error. I need to make sure whether the problem is in my side or on the other side with the service. Explored every documentation avaliable but no luck.
from google.auth.transport import requests
from google.oauth2 import service_account
from google.auth.transport.requests import AuthorizedSession
CREDENTIAL_SCOPES = ["https://www.googleapis.com/auth/cloud-platform"]
CREDENTIALS_KEY_PATH = 'my-local-service-account-key-file.json'
#the example service url I am trying to hit with requests
url = 'https://test.appspot.com/submit'
headers = {"Content-Type": "application/json"}
#example data I am sending with the request body
payload = {
"key1": "value 1",
"key2": "value 2"
}
credentials = service_account.Credentials.from_service_account_file(
CREDENTIALS_KEY_PATH,
scopes=CREDENTIAL_SCOPES
)
credentials.refresh(requests.Request())
authed_session = AuthorizedSession(credentials)
response = authed_session.request('POST',
url,
headers=headers,
data=payload
)
#adding some debug lines for your help
print(response.text)
print(response.status_code)
print(response.headers)
Getting the Output:
Invalid IAP credentials: Unable to parse JWT
401
{'X-Goog-IAP-Generated-Response': 'true', 'Date': 'Mon, 03 May 2021 06:52:11 GMT', 'Content-Type': 'text/html', 'Server': 'Google Frontend', 'Content-Length': '44', 'Alt-Svc': 'h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"'}
IAP expects a JWT(OpenID Connect (OIDC)) token in the Authorization header while your method will attach an access token the the Authorization header instead. Take a look at the below code snippet to make a request to an IAP secured resource.
Your code needs to be something like the following:
from google.auth.transport.requests import Request
from google.oauth2 import id_token
import requests
def make_iap_request(url, client_id, method='GET', **kwargs):
"""Makes a request to an application protected by Identity-Aware Proxy.
Args:
url: The Identity-Aware Proxy-protected URL to fetch.
client_id: The client ID used by Identity-Aware Proxy.
method: The request method to use
('GET', 'OPTIONS', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE')
**kwargs: Any of the parameters defined for the request function:
https://github.com/requests/requests/blob/master/requests/api.py
If no timeout is provided, it is set to 90 by default.
Returns:
The page body, or raises an exception if the page couldn't be retrieved.
"""
# Set the default timeout, if missing
if 'timeout' not in kwargs:
kwargs['timeout'] = 90
# Obtain an OpenID Connect (OIDC) token from metadata server or using service
# account.
open_id_connect_token = id_token.fetch_id_token(Request(), client_id)
# Fetch the Identity-Aware Proxy-protected URL, including an
# Authorization header containing "Bearer " followed by a
# Google-issued OpenID Connect token for the service account.
resp = requests.request(
method, url,
headers={'Authorization': 'Bearer {}'.format(
open_id_connect_token)}, **kwargs)
if resp.status_code == 403:
raise Exception('Service account does not have permission to '
'access the IAP-protected application.')
elif resp.status_code != 200:
raise Exception(
'Bad response from application: {!r} / {!r} / {!r}'.format(
resp.status_code, resp.headers, resp.text))
else:
return resp.text
Note: The above method works with implicit credentials that can be set by running command: export GOOGLE_APPLICATION_CREDENTIALS=my-local-service-account-key-file.json to set the path to your service account in the environment and then run the python code from the same terminal.
Take a look at this link for more info.

jwksError: Not Found thrown by jwks-rsa module during GET request with auth bearer token to protected api

An error - “jwksError: Not Found” is thrown when I make a get request with the correct bearer token in the request header to my protected API. I’ve followed the start up guide to create the jwtCheck helper function that I pass to all my routes to protect them. I need help clarifying what this error actually means thanks!
Here I define the helper function jwtCheck which will be used to secure all routes.
var jwtCheck = jwt({
secret: jwksClient.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: https://${auth0Domain}/.well-known/jwks.json,
}),
algorithms: ['RS256'],
issuer: https://${auth0Domain}/,
audience: auth0ApiIdentifier,
});
Then I protect my api using jwtCheck defined above like so. After which the api will throw an Unauthorized Error if one tries to send http requests to it without a header in the request with the auth bearer token.
const app = express();
...
app.use(jwtCheck);
...
I get new Bearer tokens by sending a POST request to auth0apiIdentifier/oauth/token and putting the following in the req body:
{
"client_id":id,
"client_secret":secret,
"audience":auth0apiIdentifier,
"grant_type":"client_credentials"
}
After sending the get request via postman with the appropriate bearer token in place, rwks-rsa module throws the subsequent error:
JwksError: Not found.
at ../server/node_modules/jwks-rsa/lib/JwksClient.js:119:23
at ../server/node_modules/jwks-rsa/lib/wrappers/request.js:36:12
at processTicksAndRejections (internal/process/task_queues.js:93:5)
Img 1 - POST request to get new auth Bearer token from Auth0
Img 2 - GET request sent with postman and corresponding error thrown by jwks-rsa module.
I've fixed it! The error was way too ambiguous but after desperation set in, I checked my configs again and I found that I included a "/" at the end of my auth0apiIdentifier, this allowed a "//" in the jwksUri which caused the issue. Solving this typo was my fix.
Check your code guys! Peace!

Can't set authorization and token in headers with axios in VueJS

I'm trying to set a JWT token authentication on a VueJS client and PHP API (using Zend and firebase).
I manage to log an user in with the creation of a JWT token stored in LocalStorage. Now I would like to send back this token to the API (so as to the API decode the JWT and return associated infos). I try to set the "Authorisation: Bearer + token" in the header from VueJS using axios but I always have a problem.
Here is a code snippet :
function getInfos() {
return axios({
method: 'get',
url: MYURL,
headers: {
Authorization: 'Bearer ' + localStorage.getItem('user')
}
})
.catch(handleResponse)
}
First I got this error :
Access to XMLHttpRequest at 'MYURL' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
Then I don't have any Authorization in header when I want it in my PHP API :
header("Access-Control-Allow-Origin: *");
header('Access-Control-Allow-Headers: *');
$request = new Request();
I know that I probably have to use
axios.defaults.headers.post or maybe axios.interceptors but I'm a beginner so I have no idea how to use it properly..
I hope someone will be able to help me ! Thank you
I think * doesn't work when setting custom headers you have to Type in header('Access-Control-Allow-Headers: Authorization') atleast that's an issue i had

What Bearer token should I be using for Firebase Cloud Messaging testing?

I am trying to send a test notification using Firebase Cloud Messaging via Postman. I'm doing a POST to this url
https://fcm.googleapis.com/v1/projects/[my project name]/messages:send
The Authorization tab in Postman is set to No Auth and my Headers tab looks like this
Content-Type: application/json
Authorization: Bearer [server key]
[server key] is a newly generated server key in the 'Cloud Messaging' tab of my Firebase project's 'Settings' area. I keep getting this error in response.
"error": {
"code": 401,
"message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"status": "UNAUTHENTICATED"
}
Based on everything I can find, I'm using the right token, but it seems Google disagrees. What should I be sending as the Authorization header to get past this error?
Steps to get Authentication Bearer:
Got to Google OAuth Playground: https://developers.google.com/oauthplayground
In the "Input your own scopes" for FCM use this url: https://www.googleapis.com/auth/firebase.messaging
Tap Authorize API.
Pick correct user for authorisation and allow access.
In the Step 2: Exchange authorization code for tokens tap Exchange authorisation code for tokens.
Access token is your Bearer.
Steps to send FCM using Postman:
URL to send: https://fcm.googleapis.com/v1/projects/projectid-34543/messages:send
Request Type: POST
Headers: Content-Type -> application/json & Authorization -> Bearer
In the body section enter APS payload with the right device token.
Click send.
In case you want to use cURL, for a data-notification:
curl --location --request POST 'https://fcm.googleapis.com/v1/projects/your-project-id/messages:send' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer your-access-token-*****-wqewe' \
--data-raw '{
"message": {
"token": "device-token-qwfqwee-***-qefwe",
"data": {
"Key1": "val1",
"Key2": "val2"
}
}
}'
You have to generate new access token in Postman.
First, ensure you have enabled FCM API in Google Developer Console.
Than go to Google Developer Console -> APIs & Services -> Credentials. Look at "OAuth 2.0 client IDs" section. There should be at least one item in list. Download it as json file.
In Postman open "Authorization" tab, select Type = "OAuth 2.0" than click "Get New Access Token". Dialog appears.
Fields:
Token Name - type what you want
Grant Type = Authorization Code
Callback URL = redirect_uris from downloaded json
Auth URL = auth_uri
Access Token URL = token_uri
Client ID = client_id
Client Secret = client_secret
Scope = "https://www.googleapis.com/auth/firebase.messaging"
State - leave empty
Client Authentication = default, Send As Basic Auth Header
Click "Request Token" and that's it.
The Bearer Token is the result of getting an OAuth access token with your firebase service account.
Get yourself a Firebase service account key.
Go to your firebase console > Settings > Service Accounts.
If your on Firebase Admin SDK generate new private key.
You use the service account key to authenticate yourself and get the bearer token.
Follow how to do that in Node, Python or Java here:
https://firebase.google.com/docs/cloud-messaging/auth-server.
So in Java you can get the token like this:
private static final String SCOPES = "https://www.googleapis.com/auth/firebase.messaging";
public static void main(String[] args) throws IOException {
System.out.println(getAccessToken());
}
private static String getAccessToken() throws IOException {
GoogleCredential googleCredential = GoogleCredential
.fromStream(new FileInputStream("service-account.json"))
.createScoped(Arrays.asList(SCOPES));
googleCredential.refreshToken();
return googleCredential.getAccessToken();
}
And now you can finally send your test notification with FCM.
Postman code:
POST /v1/projects/[projectId]/messages:send HTTP/1.1
Host: fcm.googleapis.com
Content-Type: application/json
Authorization: Bearer access_token_you_just_got
{
"message":{
"token" : "token_from_firebase.messaging().getToken()_inside_browser",
"notification" : {
"body" : "This is an FCM notification message!",
"title" : "FCM Message"
}
}
}
To generate an for testing push notification, you can use Google Developers OAuth 2.0 Playground
You can even send a test Push Notification using Google Developers OAuth 2.0 Playground itself.
Or if you want can use Postman / Terminal (curl command) as well.
Please find the detailed steps here, which I wrote.
Note : Instead of "Project name" in the Endpoint, you have to use "Project ID". Steps for getting the Project ID is also mentioned in the above link.
You should use definitely use Google-OAuth2.0, which can be generated using described steps in the provided link.
you can find detailed steps here, which I answered for similar question.