I am using a third-party identity provider (Ping Identity).
I have configured the client_id, redirect_uri and discovery_uri in my OpenID connect client library (https://github.com/openid/AppAuth-Android).
I was able to successfully log in and got access_token and refresh_token.
I am trying to embed some info in the access_token. But to encode i need the private key.
Question
I was wondering if there is an API that can be called with the help of the library that will encode it for me by calling the identity provider.
Thanks in advance :)
If custom claims are needed in access tokens, then they are usually included at the time of token issuance. Eg Ping Federate could make a JDBC connection to do this.
If you are using an External IDP with no relationship to your data, then perhaps this is not possible. That is why the recommendation is to avoid using foreign access tokens. Note also that access tokens are only intended for APIs and it is recommended to avoid reading them directly in web or mobile clients.
The usual technique is for the data owner to issue their own tokens after validating the external tokens, and adding any custom data / claims needed. Ideally use an Authorization Server for this, or perhaps your own API that acts as a token service, and which can store the token signing private key securely.
Related
I am developing a REST API secured via OAuth2 with Spring that will be used from an Android application (the client). In order to access any endpoint of my API, a OAuth2 access token is required and handed over to the endpoint via Authorization Header in a way similar to this:
"Authorization" - "Bearer accesstokenhere"
In order to acquire an access token, a username and password must be provided, as well as a client ID and client secret (they represent the Android app). The clientID and client secret are handed over to the token endpoint via Authorization Header in a way similar to this, which is specified by Spring:
"Authorization" - "Basic clientId:clientSecret"
If the client ID and client secret match a client defined on the server and if the user exists and the password is correct, access token and refresh token are returned.
Now my question is how I can securely store my clientId and client secret inside the Android application, making sure someone who reverse engineers my app does not get access to them?
Also, if I were to develop an iOS application (a second client), would it be wise to use a different clientID and client secret from a security POV?
You can't - even if there was a way, I could still just inspect the payload on the wire to determine the values. See section 8.5 of the OAuth 2.0 for Native Apps
Secrets that are statically included as part of an app distributed to multiple users should not be treated as confidential secrets, as one user may inspect their copy and learn the shared secret. For this reason, and those stated in Section 5.3.1 of [RFC6819], it is NOT RECOMMENDED for authorization servers to require client authentication of public native apps clients using a shared secret, as this serves little value beyond client identification which is
already provided by the "client_id" request parameter.
Your client id/secret parameters are just providing the identity of application making the request, as such it is recommended you'd want to create a different client for your iOS application, both from a security isolation point of view + for any analytics you want to gather about use of your application (e.g. 'how many sign in attempts are you retrieving by client id?' etc)
However, a threat actor could reverse engineer your settings, take your client id + secret and then start hitting your token endpoint with a username/password combo to attempt to brute force your application. If an endpoint accepts these values and returns a success/failure code, this is a useful attack vector for someone trying to compromise your system.
The current recommended approach is to use the 'Authorization code flow'
The best current practice for authorizing users in native apps is to
perform the OAuth authorization request in an external user-agent (typically the browser), rather than an embedded user-agent (such as one implemented with web-views).
Previously it was common for native apps to use embedded
user-agents (commonly implemented with web-views) for OAuth
authorization requests. That approach has many drawbacks,
including the host app being able to copy user credentials and
cookies, and the user needing to authenticate from scratch in each
app. See Section 8.12 for a deeper analysis of using embedded
user-agents for OAuth."
Have a look at AppAuth for Android for more information,
I’m implementing a Android app and that must contain a user login. To do this I create my own authenticator with the purpose of login only once. Then AccountManager can request access tokens, so the application is not handling passwords directly. The AccountManager stores the user account and the token.
I’m using JWT (Json Web Token) to authenticate the user in my REST API.
I wonder whether this flow is correct or there is a better approach to do this in Android.
Here is the flow I am currently using:
The user enter user and passwords in the login screen at first time.
I make a request to server to retrieve a valid token (JWT) that is stored in the Account Manager.
Subsequent requests use the received access token until it is expires (1 hour) to retrieve content from the API.
After the token is expired, it can be refreshed up to two weeks after issue time. From this moment, user credentials are needed to retrieve a new token.
Is this process the correct way to work with the token, and refreshing it? Is the process safe? Are there other options?
Considering this flow is not using a “refresh token” to generate a new one but the access token, what would be the best usage of the Android Account Manager? What other tools should I use? Is it recommended an Oauth2 implementation along JWT in order to implement a “refresh token”?
Cheers!
I can tell, you are on the right road of using JSON Web Tokens and reproducing it.
but the safety you mentioned is all about encrypting the token you retrieved and then saving it in Account Manager (also the same with user credentials) with some encryption method of your choice like AES or RSA and then decrypt if when you wish to use. Also using a server-generated secret key with a secret algorithm would kill the shot for any hacker.
As you understand everyone with a root access can get hands on the saved credentials database and use it.
Using these tricks will lower the need of using Oauth 2.0 which involves a refresh token.
hope it helps
I have a simple Google App Engine backend (written in Python) for an Android client. All the backend is responsible for is accepting a key and returning a value; it is a classifier in general, implemented simply by looking up the key in a Cloud SQL table, though this specific behavior will change in the future.
The backend and client communicate via Google Cloud Endpoints. I want to restrict access to my backend's API to only accept requests incoming from my client, and am wondering if OAuth 2.0 is really the way to do this.
I don't need any contextual or extra information from the user, and as such, don't want to have user action to grant any type of authorization. All I need to do is be certain the request came from my app. I was considering simply generating a static key and hardcoding it in my client and backend, but I thought there must be a more elegant way to do this.
TL;DR: How can I restrict access to my backend only to my client/app without needing user context/input, by OAuth 2.0 or otherwise?
I don't know if the OP solved their problem but I am posting this here for others. I have wasted quite a few hours on this particular issue.
Steps :
1.Create an oAuth 2.0 client ID for your Android client.
2.Specify the Client IDs in the allowed_client_ids argument of the endpoints.api. In this case (Android), supply both its Android client ID and a web client ID in allowed_client_ids.
3.Supply the audiences argument as well in endpoints.api which is set to the web client ID.
4.Add a user check to the protected methods.
5.Redeploy the API backend.
6.Regenerate the client libraries.
My Android app needs to send an authorization code to my server so that the server can use that to acquire an access token for the user's Google Drive account. I have been trying to figure out how to acquire the authorization code and I found this in the Google API documentation (Using OAuth 2.0 for Installed Applications):
This sequence starts by redirecting a browser (system browser or
embedded in the application as a web view) to a Google URL with a set
of query parameters that indicate the type of Google API access the
application requires. Like other scenarios, Google handles the user
authentication and consent, but the result of the sequence is an
authorization code. The authorization code is returned in the title
bar of the browser or as a query string parameter (depends on the
parameters sent in the request).
After receiving the authorization code, the application can exchange
the code for an access token and a refresh token. The application
presents its client_id and client_secret (obtained during application
registration) and the authorization code during this exchange. Upon
receipt of the refresh token, the application should store it for
future use. The access token gives your application access to a Google
API.
Now I am not sure how to get this authorization code in my Android app since the Android examples I have seen seem to get the access tokens directly. I am looking at the Android AccountManager class and it has a method getAuthToken but this seems to refer to the access token and not the authorization code.
So how does one acquire the authorization code that can be shared with a server? If it is possible I would greatly appreciate some example code. If this is not possible what are the possible workarounds?
You may want to take a look at the Cross-client Identity document. It should keep you from needing to pass user tokens back and forth.
I believe you can actually take the access token returned by the Android AccountManager, send this to your server, then have your server make a call against the Google Drive API using that same access token - it is a bearer token and not bound to the channel that created it, so please take good care of it and only send over encrypted connections.
Documentation on how to get that access token can be found here:
https://developers.google.com/drive/quickstart-android
While that access token is good for immediate use, it will expire in less than 1 hour, so if you are looking for a solution that enables your backend server to have continued access to the Drive data, without the user being present at your app at the time of request, an alternate approach will be needed.
I have a android application which sends updates about the purchases for the server. What I do now is, I encrypt the purchases and some other shared details into MD5, using the same key generator in server side and Android Client side. But if some one decode the APK file that person can easily make the calls by generating keys. What is the best way to prevent these kinds of attacks?
Use HTTPS to communicate with you server in order to protect data in transit. Do not try to invent a secure protocol. If you want to restrict access to server API's use some form of authentication: username and password (over HTTPS) or better yet some sort of authentication token (OAuth, etc.). If you store keys and/or passwords inside the APK, anyone can extract them by decompiling the APK. If you want to protect against this, you need to use token authentication where tokens expire and can be invalidated if compromised.
Best Solution is that you implement some web service which will return you a access key(will change every time you want to get access key) which you will use every time to communicate with your server in POST method. This is most secure method and being used by every good sites like Facebook, Twitter etc.
Sine my problem was basically about updating the server with in-app purchases, I ended up doing Public/Private key authentication at the server end. Android suggest to verify receipts on client, but we just forward the receipts to server and did validation there using the public key.