I am currently setting up a fresh instance of WSO2 AM 3.2.0 from scratch because upgrading and migrating from version 2.1 did not work as expected. To avoid any inconvenience for current users I would like to keep using the already existing consumer_key and consumer_secret for each application so the access_token doesn't change when transitioning from 2.1 to 3.2.
Assume the consumer_key:consumer_secret being in use in version 2.1 is: original_key:original_secret.
When creating a new application in the AM 3.2 instance I, of course, get a new secret - say new_key:new_secret. To keep using the original combination I created a dump of the AM 3.2 database and in this dump I just replaced the new consumer_key and consumer_secret with the original ones like this:
sed -i 's/new_key/original_key/g' dump.sql and sed -i 's/new_secret/original_secret/g' dump.sql
and then I replaced the existing 3.2 database with this modified dump. After restarting the AM 3.2 I can see that the application is in fact using the original consumer_key and consumer_secret but when I generate an access_token it differs from the original access_token which I actually wanted to replicate.
I know that my approach is rather dirty but I'm wondering why it didn't work, though. Is there anything I missed -- or even better -- a clean solution for my problem?
The reason for getting the different access token is that apim 3.2.0 only supports JWT tokens by default, in 2.1.0 it only supports opaque tokens. I believe that you are getting JWT tokens with the above token calls which are different from opaque tokens.
In the above approach, you will lose the following data from the previous 2.1.0 setup.
APIs and artifact related information.
Application attributes + existing active tokens + scopes
Users that persisted in the existing platform.
However, if you just want to replicate the applications with client id and secret, the better approach would be as follows.
Using Devportal REST API
Use the dev portal rest APIs to create the application[1]. When providing the parameters specify the token type as OAUTH if you want to obtain an opaque token.
Map the client-id secret pair using map-keys resource[2]
I hope the above will be helpful to you.
[1]https://apim.docs.wso2.com/en/latest/develop/product-apis/devportal-apis/devportal-v1/devportal-v1/#tag/Applications/paths/~1applications/post
[2]https://apim.docs.wso2.com/en/latest/develop/product-apis/devportal-apis/devportal-v1/devportal-v1/#tag/Application-Keys/paths/~1applications~1{applicationId}~1map-keys/post
Related
I am migrating old API manager to 4.1 (with one Gateway-worker and one Control-plane) and I want to reuse existing access token and set it in database.
In the old version, an API has an access token with infinite lifetime. This token is deployed in mobile apps, and it is not acceptable to regenerate a new token and redeploy the mobile app.
Actually, I have created the API in the new version (4.1). I'm using opaque token, and I can request this API with the opaque token. I just want to use my old access token instead.
I've tried to set this token in database :
UPDATE "IDN_OAUTH2_ACCESS_TOKEN" SET ACCESS_TOKEN = '64a84d453e9259d2104210035d8436f4',
ACCESS_TOKEN_HASH = '{"hash":"4cf7cd7f4ddc89b9900554bcf8e3ca71c605c59b278b3996a330f1fd4a3ff372","algorithm":"SHA-256"}'
WHERE ROWID = 'xxx'
Then I've restarted the gateway for clearing token cache.
I have tested options for disabling token cache : (just for testing)
[apim.cache.gateway_token]
enable = false
[apim.cache.km_token]
enable = false
[apim.cache.restapi_token]
enable = false
When I request a token, my old token is correctly returned by the key manager :
curl -k -X POST https://my-keymanager.dev/oauth2/token -d "grant_type=client_credentials" -H"Authorization: Basic XXXXX"
{"access_token":"64a84d453e9259d2104210035d8436f4","scope":"default","token_type":"Bearer","expires_in":xxx}
But when I try to call the API with this token,
curl -k -X GET "https://my-gateway.dev/test-api/32155" -H "accept: application/json" -H "Authorization: Bearer 64a84d453e9259d2104210035d8436f4"
I have always this error :
{"code":"900901","message":"Invalid Credentials","description":"Access failure for API:
/my-Api/v2.0.0, version: v2.0.0 status: (900901) - Invalid Credentials.
Make sure you have provided the correct security credentials"}
DEBUG {org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler} - API authentication failed with error 900901 org.wso2.carbon.apimgt.gateway.handlers.security.APISecurityException: Access failure for API: /eQuilibre/v2.0.0, version: v2.0.0 status: (900901) - Invalid Credentials
at org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler.isAuthenticate_aroundBody56(APIAuthenticationHandler.java:536)
at org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler.isAuthenticate(APIAuthenticationHandler.java:516)
at org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler.handleRequest_aroundBody46(APIAuthenticationHandler.java:402)
at org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler.handleRequest(APIAuthenticationHandler.java:353)
at org.apache.synapse.api.API.process(API.java:403)
I think there is another step because the gateway don't call the key manager when I call the API.
How can I tell the Gateway to accept the new token ?
EDIT 1 :
I'm using Opaque token in API Manager 4.1 :
How to create an application that generate Opaque token in WSO2 APIM Manager 4.x versions
EDIT 2 :
I'm migrating from 2.6, but it should be the same problem with another version with opaque token. The only think I want to migrate is the value of the token.
Actually, I have created the API in the new version (4.1). I'm using
opaque token, and I can request this API with the opaque token. I just
want to use my old access token instead.
First of all, we no longer support Opaque tokens out-of-the-box in our latest product versions.
I am migrating old API manager to 4.1 (with one Gateway-worker and one
Control-plane) and I want to reuse existing access token and set it in
database.
From which version of API Manager are you trying to migrate? The source version is not mentioned. If the source deployment also has JWT tokens, you can migrate existing tokens into the new deployment by migrating your database using our migration scripts.
Based on the error message, I belive you are trying to invoke the new API with the old Opaque access token, whereas the new API Manager 4.1 uses the JWT token by default.
Contact WSO2 Support via [1] for any further support.
[1] https://apim.docs.wso2.com/en/latest/install-and-setup/upgrading-wso2-api-manager/upgrading-api-manager/
Yes, if you follow our standard migration scripts, you can migrate existing opaque tokens (that's what is used by APIM v2.6) as it is and your existing applications will continue to function as usual. Only the new applications will use JWT tokens.
I am using Django 4.0 with python 3.9 and I installed drf-social-oauth2 in my app. I was using the now depreciated gapi Oauth2 for google login and it worked fine. Then I started getting warnings in my console that it'll not be in use for some time to come so I changed to the new google Identity Service(gsi client). What I used to get from gapi was an access_token which I use to verify users on my backend. now I get a credential jwt which I'm supposed to decode to get user details.
when I send this code to the /auth/convert-token/ end point, I get AccessDeniedError at /auth/convert-token (access_denied) Your credentials aren't allowed <oauthlib.Request SANITIZED>
all my details are correct and I'm stuck.
Tested this using vscode thunder client.
I have found a solution. turns out the jwt isn't what I'm supposed to send to my backend. I used the jwt token to get an access token for the user which I then used to authenticate the user on my backend.
I'm building a custom Power BI DataConnector which uses OAuth. I'm following the github example. But this stores client credentials (required for the 'code flow' in OAuth) as plain text files. Is there a secure alternative to this ?
Unfortunately due to the current "state of the art" there is no way to securely protect these credentials according to Microsoft staffer Curt Hagenlocher:
There is no way to protect a secret on someone's desktop. That's why some OAuth providers (like AAD) support a "native app" mode where there's a client id but no secret. The most recent development in this space is PKCE, and we're aiming to have sample code for that later this year.
In principle, a secret could be supplied separately for service use -- and I'd like to see us do that some day -- but there's a lot of infrastructure which would need to be created to support that.
I suggested encryption of the module itself and Curt's response was that this too would be ineffective:
All someone needs to do is have Fiddler running and they can see
exactly what secret is being sent to the token endpoint.
Full conversation:
https://github.com/microsoft/DataConnectors/issues/298
I am trying to develop mobile native apps with ionic2 and django rest framework. And I found django-rest-framework-jwt library that support great jwt authentication. However it doesn't refresh token automatically so that users of mobile apps should type their username and password whenver the token expires..
I already checked another stackoverflow question below.
JWT (JSON Web Token) automatic prolongation of expiration
Is there any way that users don't have to type their username and password again? Or Is it ok let token not to be expired and save it local storage of mobile apps so that users don't have to login again?
Thanks in advance!
I've run into the same scenario with our Django and DRF-based projects, and we wanted to implement Single sign-on using JWT. Since the djangorestframework-jwt library had very little focus on providing SSO capabilities between different projects, I have created a new library for this that properly sets up trust definitions and public/private key pairs.
This library provides two types of JWT tokens:
non-expiring session tokens for your primary login application (aka. "refresh tokens")
short-lived authorization tokens for accessing your other apps (these contain permissions given by the primary app)
The client is expected to first login to your primary login application by POSTing an username and password. The client will receive a permanent session token that will allow subsequent requests to the same server be authenticated. These tokens do not contain any permissions/authorization information and cannot be used for SSO into other apps.
Afterwards, the client is expected to obtain and keep updating authorization tokens using the session token. These secondary tokens are short-lived (15mins..1 hour) and contain the permissions that the user has at the time of issuance. These tokens are used to access other services, which then trust the permissions in the JWT payload for the lifetime of the token.
The current version is v0.0.3 (alpha), but we are moving very fast towards a beta and finally production quality release. The API is already relatively stable and should be final by June 30th 2016. The framework will also have full test coverage in the coming weeks, when we reach the beta stage.
Please check the project page and github for the README.
https://pypi.python.org/pypi/djangorestframework-sso
https://github.com/namespace-ee/django-rest-framework-sso
Please let me know if this would fit your use case, and if it has all the features required. I'll be happy to help with the setup.
I used to get the user's username in the API 1.0 fairly easily, using /me and getting the username property of the response object.
Now I'm getting this error with API 2.0:
"(#12) username is deprecated for versions v2.0 and higher"
The only way I found to get this until now was to use FQL, but now it seems deprecated.
Is there a way around this?
I don't mean to be unhelpful, but it appears access to username has been removed from the API, as far as I can tell. Places where an app may have been using username, such as in the old share dialogs, can no longer do that when used with the 2.0 API. I think its also a way of preventing apps from having access to usable unique identifiers outside of the app scope - any user IDs you retrieve under 2.0 API are specific to your app alone.
I found a simple workaround that involves a get request to Facebook. Instead of the username, Facebook will give you an ID that is unique to your application.
I have found that making a request to https://www.facebook.com/[profile_id] will then redirect to the user's real profile. The username can be extracted from the redirect URL.
Example:
> curl -i https://www.facebook.com/710290539
HTTP/1.1 301 Moved Permanently
Location: https://www.facebook.com/colinskow
(Note: Since I am the owner of the app in test mode, this could possibly be an exception. Please let me know in comments if you are able to confirm this in a production environment.)
As a workaround you can use the email as a unique identifier. Email address can be retrieved using "email" as the permission scope.
Facebook has removed the username field from the new API version. It is not possible to retrieve the username. But Facebook provides an application specific unique ID. If you need to share the same user between several apps you can use the newly introduced Business Mapping API. This allows to add all the required apps to a group. In this case the ID will be unique among all the apps in the group.
More information on Business Mapping API is available at https://developers.facebook.com/docs/apps/for-business 1