Authorizing wikimedia API usage: rest-read-denied error - wikipedia-api

I'm trying to fetch a decent number of API URLs like https://api.wikimedia.org/core/v1/wikipedia/en/file/File%3AFlag%20of%20Madison%20Heights%2C%20Michigan.svg.
I have signed up for an API key as described in the instructions.
However, when I issue my requests with the Authorization: Bearer [long JWT Access Token goes here] header, I just get {"error":"rest-read-denied","httpCode":403,"httpReason":"Forbidden"} back.
If I omit the Authorization header, then I do get a good response, but am severely rate limited.
The API Portal says that my API key is approved. I have tried resetting the secret, and have tried creating a separate one, I have inspected the exact headers sent by using curl -v and I can see the Authorization header in there and it looks correct (diffed it with the access token).
If I modify the token, then I get a different error message: {"httpCode":401,"httpReason":"Jwt verification fails"} so clearly my token is passed in correctly and it's a permissions issue with my API key. I have tried both a key with read only permission, and a key with both read & edit permissions, but no dice.
The example cURL request in the signup instruction also fails with a rest-read-denied error:
curl -H "Authorization: Bearer $AccessToken" \
https://api.wikimedia.org/core/v1/wikipedia/en/page/Earth/bare
!?!?

Related

Trying to login using oauth. Can someone explain the documentation how to get access token?

I understand that I need to call:
curl --request POST \
--url 'https://auth.atlassian.com/oauth/token' \
--header 'Content-Type: application/json' \
--data '{"grant_type": "authorization_code","client_id": "YOUR_CLIENT_ID","client_secret": "YOUR_CLIENT_SECRET","code": "YOUR_AUTHORIZATION_CODE","redirect_uri": "https://YOUR_APP_CALLBACK_URL"}'
to get access token. There is some attempt to explain what are client_id, client_secret, code, redirect_uri, but it's totally cryptic to me. Can someone explain to me, what these are and where to get them?
I can login to company jira. I can create my personal access token in my profile. I cant get any meaningful support from my company. I need to get somehow from here to access token, so that I can call rest api.
OAuth needs that the user login through a web interface.
Once logged, is possible to retrieve the code you are looking for in the URL.
In my case, in order to get that code I have to open the oauth login web page of the service I want to use (in your case atlassian) and just login.
I usually manage this process with code, not using curls.
redirect_uri is where you want to be redirected after you login in the web interface.
i.e. Do I need to login with atlassian in order to call api and use data from my app ?
mobile app/Desktop App (redirect_uri will be a schema defined by you in the app, could be something like: myCompany://myApplicationExample or with desktop http://localhost should work ). In this case I suggest you to read something about deeplink for applications.
website (redirect_uri will the url of your website : https://yourwebsite.com
In my case, with the services I usually work with, cliend_id and client_secret are given per user or per application, when requested to the company which provides services you need.
I hope this can help you clarify
BY THE WAY:
if you say you already have an Access Token , you should be able to do everything without Loggin in, because the final purpose of login and use all this parameters you asked for, is to get an Access Token.
The endpoint you are trying to call, will just return you an Access Token.
The Access token is what you need in order to call rest api in this case.
I would suggest you to try to call an atlassian rest API you want, using the Access Token you already have in the headers of the rest API, and see the results.
In my case, I have to create an header like this:
Authorization : Bearer {your Access token}
I hope this helps you.
EDIT:
As shown in point 1 in this doc https://developer.atlassian.com/cloud/jira/platform/oauth-2-3lo-apps/
you should open this url by your application:
https://auth.atlassian.com/authorize?
audience=api.atlassian.com&
client_id=YOUR_CLIENT_ID&
scope=REQUESTED_SCOPE_ONE%20REQUESTED_SCOPE_TWO&
redirect_uri=https://YOUR_APP_CALLBACK_URL&
state=YOUR_USER_BOUND_VALUE&
response_type=code&
prompt=consent
read the doc on you should set redirect_uri (http://localhost is valid if is a desktop application, but you will have to implement an http listener in order to get the authorization code, I suggest you to set a schema in you app or simply use a web page url).
You should get a client_id by atlassian to use in the url,same for scope.
I don't know exaclty the state parameter but in the docs should be writtend.
Once logged you will be redirected to the redirect_uri you set, getting also this authorization_code, then you can call the /token endpoint in order to get the Access Token.
curl --request POST \
--url 'https://auth.atlassian.com/oauth/token'
--header 'Content-Type: application/json'
--data '{"grant_type": "authorization_code","client_id": "YOUR_CLIENT_ID","client_secret": "YOUR_CLIENT_SECRET","code": "YOUR_AUTHORIZATION_CODE","redirect_uri": "https://YOUR_APP_CALLBACK_URL"}'
Here you have to use the authorization code you get from the login, re use the same client_id, set also the client_secret (should be given with the client_id) and re use the same redirect_uri you used in the login url.
Once done you will have finally the Access Token, which must be used in order to call Apis.
as shown in the doc you should be able to call apis like this curl
curl --request GET \
--url https://api.atlassian.com/oauth/token/accessible-resources
--header 'Authorization: Bearer ACCESS_TOKEN'
--header 'Accept: application/json'
Where 'ACCESS_TOKEN' will be your access token obtained before.
Remind that an Access Token usually has an expiration date, after which you will need to login again or refreshing the token.
EDIT 2:
A Client ID is an identifier associated with an application that assists with client / server OAuth 2.0 authentication.
So basically is a constant string, this should be given to you from atlassian/jira in some way.
Client Secret should be given to you with Client ID from atlassian/jira.
Client_id and client_secret usually are also called api keys.
Usually the Scope is the name of the application you are requesting api keys for (you should request new api keys for each application),this is up to you, and should be comunicated to the company in your case (atlassian/jira) when requesting api keys.
(i.e. For my company I work with Trimble Connect, which is just a platform, everytime I develop for example a plugin/addon on top of it I ask them new api keys)
for what concerns the state:
state: (required for security) Set this to a value that is associated with the user you are directing to the authorization URL, for example, a hash of the user's session ID. Make sure that this is a value that cannot be guessed. You may be able to generate and validate this value automatically, if you are using an OAuth 2.0 client library or an authentication library with OAuth 2.0 support.
In the beginning I would try to give the state a random value.
I think you should ask to Atlassian how to get your api keys (maybe there's a page for that, like for Trimble Connect in my case).
I would send them an e-mail.
Seems you are not interested in call Apis from an application you are developing, but just from curls.
if I'm right, I know I have already told you, but if I were you I would definitely try to call an atlassian API not trying to get the access token from the OAuth Login, but using that ACCESS TOKEN you told me you told me you manually created.
Please try this curl:
curl --request GET \
--url https://api.atlassian.com/oauth/token/accessible-resources
--header 'Authorization: Bearer {ACCESS_TOKEN}'
--header 'Accept: application/json'
just use your Access Token string instead of {ACCESS_TOKEN} and see the results.

GCP REST api authentication missing

I have created a job of JDBC to BigQuery using the web interface and it worked just fine.
Now I want to create the same job from the REST API of GCP so I took the rest equivalent of the request from the site and tried to send it from Postman.
I'm sending POST request for the following URL:
https://dataflow.googleapis.com/v1b3/projects/test-data-308414/templates:launch?gcsPath=gs://dataflow-templates/latest/Jdbc_to_BigQuery
which I got from the example in the GCP documentation.
I also pass the JSON that the GCP gave me in the body.
And the API key as get parameter in the next format "?key=[API_KEY]"
I'm getting 401 response from the server with the following message:
Request is missing required authentication credential. Expected OAuth
2 access token, login cookie or other valid authentication credential.
See
https://developers.google.com/identity/sign-in/web/devconsole-project.
With a status of:
UNAUTHENTICATED
I looked up at the link and found a tutorial on how to create google authentication on the front end
witch is not helpful to me.
I'm pretty sure that I'm passing the API key in the wrong format and that the reason it failed to authenticate.
But I couldn't find any documentation that says how to do it correctly.
PS> I have also tried passing it at the headers as I saw in one place
in the next format
Authorization : [API_KEY]
but it failed with the same message
Few days back I was trying to integrate GCP into MechCloud and struggling to figure out how to invoke a microservice ( which is acting as a proxy to GCP) with credentials for different projects which will be passed to this microservice on the fly. I was surprised that in spite of spending good amount of time I could not figure out how to achieve it because GCP documentation is focused on working with one project credentials at a time using application default credentials. Another frustrating thing is that API explorer shows both OAuth 2.0 and API Key by default for all the APIs when the fact is that API Key is hardly supported for any API. Finally I found the solution for this problem here.
Here are the steps to invoke a GCP rest api -
Create a service account for your project and download the json file associated with it.
Note down values of client_email, private_key_id and private_key attribues from service account json file.
Define following environment variables using above values -
GCP_SERVICE_ACCOUNT_CLIENT_EMAIL=<client_email>
GCP_SERVICE_ACCOUNT_PRIVATE_KEY_ID=<private_key_id>
GCP_SERVICE_ACCOUNT_PRIVATE_KEY=<private_key>
Execute following python code to generate jwt_token -
import time, jwt, os
iat = time.time()
exp = iat + 3600
client_email = os.getenv('GCP_SERVICE_ACCOUNT_CLIENT_EMAIL')
private_key_id = os.getenv('GCP_SERVICE_ACCOUNT_PRIVATE_KEY_ID')
private_key = os.getenv('GCP_SERVICE_ACCOUNT_PRIVATE_KEY')
payload = {
'iss': client_email,
'sub': client_email,
'aud': 'https://compute.googleapis.com/',
'iat': iat,
'exp': exp
}
private_key1 = private_key.replace('\\n', '\n')
# print(private_key1)
additional_headers = {'kid': private_key_id}
signed_jwt = jwt.encode(
payload,
private_key1,
headers=additional_headers,
algorithm='RS256'
)
print(signed_jwt)
Use generated jwt token from previous step and use it as a bearer token to invoke any GCP rest api. E.g.
curl -X GET --header 'Authorization: Bearer <jwt_token>' 'https://compute.googleapis.com/compute/v1/projects/{project}/global/networks'
The best practice to authenticate a request is to use your application credentials. Just make sure you installed the google cloud SDK.
curl -X POST \
-H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
-H "Content-Type: application/json; charset=utf-8" \
-d #request.json \
https://dataflow.googleapis.com/v1b3/projects/PROJECT_ID/templates:launch?gcsPath=gs://dataflow-templates/latest/Jdbc_to_BigQuery

How to use "user context access token" that I get from Twitter OAuth 1.0a in my request?

I have successfully (?) implement the Twitter three-legged authentication process to obtain user access token. The problem is the access token appears invalid... or I use it wrong. I already able to get the app's access token, which can access limited Twitter API. I use it by adding "Authentication: Bearer 'access token'" on the header. But when I did the same thing with the user context access token and did the same request, I always get error code 89 Invalid or expired token.
The access token I obtained has a structure of [several numerics]-[some alpha numeric chars]. Like 12345678-asd98f798asdf79asdfa9sdfs9df7a9sdf7. This looks similar with the access token example in step 3 of https://developer.twitter.com/en/docs/basics/authentication/oauth-1-0a/obtaining-user-access-tokens.
I also notice that the example request there is like this:
POST statuses/update.json
oauth_consumer_key=cChZNFj6T5R0TigYB9yd1w
oauth_token=7588892-kagSNqWge8gB1WwE3plnFsJHAZVfxWD7Vb57p0b4
Which I presume those two additional parameters are to be added to the body instead of the header. But, how if my request is a GET request? Like request to get home timeline, which absolutely requiring user context access token?
https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-home_timeline
From this API ref, the example only give the GET url, and not how to supply the user context access token. Please help. I have the feeling that the solution is very simple (like a fix on the header), but I can't see it.
This is my current request:
curl -X GET \
'https://api.twitter.com/1.1/users/show.json?screen_name=huffpost' \
-H 'Authorization: Bearer 12345678-as3d12a3d1a3sd1232ads13asd123as1d23as3d32,Bearer 12345678-as3d12a3d1a3sd1232ads13asd123as1d23as3d32' \
This is the result:
{
"errors": [
{
"code": 89,
"message": "Invalid or expired token."
}
]
}
The user access token requires signing a request which includes parameters and headers.
https://developer.twitter.com/en/docs/basics/authentication/oauth-1-0a/authorizing-a-request
You can use a library like https://github.com/twitter/joauth to generate the signature.
For Java+OkHttp - you can use this library https://github.com/yschimke/okurl/blob/master/src/main/kotlin/com/baulsupp/okurl/services/twitter/joauth/Signature.kt#L33

Unable to generate refresh token for IBM Visual Recognition API

I am trying to work with IAM token based authentication. I am able to generate 'access token' and could do operations using the 'access token'. Now I am having issue while generating 'refresh token'. I am following this link https://cloud.ibm.com/docs/services/watson?topic=watson-iam.
I am using below command to generate refresh token. Here Authorization header value obtained using username as 'apikey' and value as my key. {refreh-token} value I am using which I received while generating 'access token'.
curl -k -X POST --header "Authorization: Basic Yng6Yng=" --data-urlencode "grant_type=refresh_token" \ --data-urlencode "refresh_token={refresh-token}" "https://iam.bluemix.net/identity/token"
I expect to get refresh token but get error {"context":"requestId":"021c3482...""},"errorCode":"BXNIM0507E","errorMessage":"For OpenID Connect related APIs, you need to send your client credentials as basic authorization header"}
Can some one help me in understanding what is going wrong
The description in https://cloud.ibm.com/docs/services/watson?topic=watson-iam is incorrectly describing the refresh case. I will follow-up with the docs team to update that section.
This is the generic description how to get tokens for API keys:
https://cloud.ibm.com/docs/iam?topic=iam-iamtoken_from_apikey
For API usage, IBM Cloud allows you to generate access token's without providing a client id / secret. In this case, a default client id is assumed which is only allowed to create tokens for API keys, but not authorized to use any other grant type - including the grant_type refresh_token. Therefore, simply dismiss the refresh token from the response of the API key grant in the first call - you won't be able to use it.
In the API key use case, there is no benefit of using the grant_type refresh_token over getting a new access token with the API key grant type anyway - all validation steps that are done internally (does the user stil exist / is the user still in the account / ...) are identical. But the refresh token eventually will expire - the API key not.

Salesforce OAuth2 missing_oauth_token

I am doing all the steps to gain an oauth token for salesforce but unable to workout the final step. I want to gather the Users information (email, first name, lastname, thumbnail).
So I get to the step where I can get this information :
<OAuth>
<id>
https://login.salesforce.com/id/00D90000000qdxPEAQ/00590000001hbAyAAI
</id>
<issued_at>1386648423427</issued_at>
<scope>id chatter_api</scope>
<instance_url>https://ap1.salesforce.com</instance_url>
<signature>YlnejSL3ZKkSmbnt916sLZuzt13UNUFGi+kGCjU7ql0=</signature>
<access_token>
00D90000000qdxP!AQsAQIcR.oo6y.EDuf3B4fzctQ2e7DK0L1kGjgxGSl.dBgetu3lUbZp.VDZjSIi7O1LXmTMWFZmOJVeRS.IQfvPL8VmhxLaC
</access_token>
</OAuth>
but from here, I am not sure how to get the users information (returned as XML or JSON).
From a browser, can't I go to https://login.salesforce.com/id/00D50000000IZ3ZEAW/00550000001fg5OAAQ followed by some auth key? (I dont have CURL installed).
Whenever I try go to this in the URL it states
Missing_OAuth_Token
I used to develop something using Google OAuth,so I tried request like https://login.salesforce.com/id/00D50000000IZ3ZEAW/00550000001fg5OAAQ?access_token=access_token(this format is supported by Google OAuth), but unfortunately I get response "Missing_OAuth_Token", just like what you did. Then I refer to salesforce document, and found that it only support the format like:
curl https://instance_name.salesforce.com/services/data/v20.0/ -H 'Authorization: Bearer access_token'
You need to put access_token in the header of the request, so install CURL, or send the request in your program with access_token in header.
You are on the right tracks, you can do a GET on the id URL, but you need to supply the access token in the Authorization header, e.g. Authorization: Bearer {accessToken}