Using OAuth 2.0 for Web Server Applications, verifying a user & #39; s Android in-app submodules, oauthin-app

Source: Internet
Author: User

Using OAuth 2.0 for Web Server Applications, verifying a user's Android in-app submodules, oauthin-app

Before writing this article, let's talk about some additional things.

Some time ago, the game was eager to go online on GoolePlay. I knew that if Auth2.0 verification is not secure or I skipped this step for the time being, I found that the background record was not consistent with the actual payment for the player in a few days, suspected players have stolen the game ingot and so on, and truly passed all the payment procedures of GooglePlay to complete the item exchange, a long time serious can be imagined. After reading a large number of official google Documents, add the code and record the use of OAuth 2.0. Google provides several usage methods of OAuth2.0, each of which is somewhat different, for details, refer to this blog. Here, we only write the usage of OAuth 2.0 for Web Server Applications, which involves obtaining and using refresh_token and access_token, and how to send GET and POST requests to google, finally, the user verifies the payment and purchase information in the Android app.

First, I posted the Official Google article about Using OAuth 2.0 for Web Server Applications:

The authorization sequence begins when your application redirects a browser to a Google URL; the URL provided des query parameters that indicate the type of access being requested. as in other scenarios, Google handles user authentication, session selection, and user consent. the result is an authorization code, which Google returns to your application in a query string.
After Authentication ing the authorization code, your application can exchange the code (along with a client ID and client secret) for an access token and, in some cases, a refresh token.
The application can then use the access token to access a Google API.
If a refresh token is present in the authorization code exchange, then it can be used to obtain new access tokens at any time. this is called offline access, because the user does not have to be present at the browser when the application obtains a new access token.

Through the original text and illustration, we can know such a process (which will be described in detail below ):

1. Create a Web Application account in the Google Developer Console and obtain client_id, client_secret, and redirect_uri. The following three parameters are commonly used (prerequisite)

2. obtain Authorization code

3. Use code to obtain access_token and refresh_token

4. You can use refresh_token to obtain the new access_token.

5. Use access_token to call Google API for final purpose (if access_token is out of date, go back to step 4)

Note: in step 3, when we use code to obtain access_token for the first time, Google will return you a refresh_token at the same time, if you use code to retrieve access_token again in the future, you will not see refresh_token again, so you must save it. This refresh_token is valid for a long time. If it is not explicitly revoked by the application manager, it will not expire, and the access_token is only valid for 3600 seconds, that is, one hour. The problem arises, what is the relationship between access_token and refresh_token? Obviously, we finally need to use access_token to call the Google API, and access_token has a limitation of validity. Therefore, when access_token expires, we can use a long-lived refresh_token to obtain the access_token again, it can be obtained multiple times at any time without limit on the number of times. In fact, when we get the refresh_token, It is a turning point.

The detailed decomposition steps are as follows:

1. Create a Web Application account in the Google Developer Console.

(The new Google Developer Console page is used here. You can set it to Chinese in Account settings ~)

4. You can enter it at will. After creation, you can see the following:



Here we get three key parameters: client_id, client_secret, redirect_uris, in the following steps.

Some people may wonder, how can we determine that the project created on the google developer console is associated with the Android Application launched on Googleplay? Why can I use the access_token obtained by these parameters to call Google APIs? In fact, there are associated project operations when Googleplay releases an application. Then, the project creator can grant permissions to other Google accounts, in this way, other Google accounts can directly view the project and the following web applications on their developer console page, and can log on to their Google account to obtain the code in the next step.


2. obtain Authorization code

https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/androidpublisher&response_type=code&access_type=offline&redirect_uri={REDIRECT_URIS}&client_id={CLIENT_ID}

We need to open this URL in the form of a browser. Then we will prompt you to Sign in with your Google Account, and then log on to the Google Account with project authorization, the code we need will appear in the address bar. Example: https://www.example.com/oauth2callback? Code = 4/CpVOd8CljO_gxTRE1M5jtwEFwf8gRD44vrmKNDi4GSS.kr-GHuseD-oZEnp6UADFXm0E0MD3FlAI


3. Use code to obtain access_token and refresh_token

https://accounts.google.com/o/oauth2/token?code={CODE}&client_id={CLIENT_ID}&client_secret={CLIENT_SECRET}&redirect_uri={REDIRECT}&grant_type=authorization_code

The purpose of this step is to obtain the refresh_token. With this long-acting token, the access_token can be obtained at any time. The JSON string obtained from the first request is as follows, refresh_token will no longer appear for future requests. Save the refresh_token. Expires_in indicates the validity period of access_token, Which is 3600 seconds.

{    "access_token": "ya29.3gC2jw5vm77YPkylq0H5sPJeJJDHX93Kq8qZHRJaMlknwJ85595eMogL300XKDOEI7zIsdeFEPY6zg",     "token_type": "Bearer",     "expires_in": 3600,     "refresh_token": "1/FbQD448CdDPfDEDpCy4gj_m3WDr_M0U5WupquXL_o"
}

4. You can use refresh_token to obtain the new access_token.

https://accounts.google.com/o/oauth2/token?grant_type=refresh_token&client_id={CLIENT_ID}&client_secret={CLIENT_SECRET}&refresh_token={REFRESH_TOKEN}

Here we want to initiate a POST request to Google. the JAVA code is as follows:

/** Get access_token **/private static Map <String, String> getAccessToken () {final String CLIENT_ID = "fill in your client_id "; final String CLIENT_SECRET = "fill in your client_secret"; final String REFRESH_TOKEN = "fill in the refresh_token obtained in the previous step"; Map <String, String> map = null; try {/*** https://accounts.google.com/o/oauth2/token? Refresh_token = {REFRESH_TOKEN} * & client_id = {CLIENT_ID} & client_secret = {CLIENT_SECRET} & grant_type = refresh_token */urlGetToken = new URL ("https://accounts.google.com/o/oauth2/token "); httpURLConnection connectionGetToken = (HttpURLConnection) urlGetToken. openConnection (); connectionGetToken. setRequestMethod ("POST"); connectionGetToken. setDoOutput (true); // start transmission parameter OutputStreamWriter writer = new O UtputStreamWriter (connectionGetToken. getOutputStream (); writer. write ("refresh_token =" + REFRESH_TOKEN + "&"); writer. write ("client_id =" + CLIENT_ID + "&"); writer. write ("client_secret =" + CLIENT_SECRET + "&"); writer. write ("grant_type = refresh_token"); writer. close (); // if the response code is 200, the request is successful if (connectionGetToken. getResponseCode () = HttpURLConnection. HTTP_ OK) {StringBuilder sb = new StringBuilder (); BufferedReader Reader = new BufferedReader (new InputStreamReader (connectionGetToken. getInputStream (), "UTF-8"); String strLine = ""; while (strLine = reader. readLine ())! = Null) {sb. append (strLine);} // get the information returned by Google (JSON format) JSONObject jo = JSONObject. fromObject (sb. toString (); String ACCESS_TOKEN = jo. getString ("access_token"); Integer EXPIRES_IN = jo. getInt ("expires_in"); map = new HashMap <String, String> (); map. put ("access_token", ACCESS_TOKEN); map. put ("expires_in", String. valueOf (EXPIRES_IN); // The Creation Time of the imported access_token, used to determine whether the map is invalid. put ("create_time", String. valueOf (new Date (). getTime ()/1000); logger.info ("JSON information containing access_token:" + jo) ;}} catch (MalformedURLException e) {logger. error ("failed to get access_token because:" + e); e. printStackTrace ();} catch (IOException e) {logger. error ("failed to get access_token because:" + e); e. printStackTrace ();} return map ;}

5. Use access_token to call Google API for final purpose (if access_token is out of date, go back to step 4)

Here, I need to obtain the purchase information I paid for GooglePlay in the app. This information includes the following attributes: (refer to the Purchases. products under Google Play Developer API)

A ProductPurchase resource indicates the status of a user's inapp product purchase.

{"Kind": "androidpublisher # productPurchase", "purchaseTimeMillis ":Long, "PurchaseState ":Integer, (Purchased: 0 canceled: 1, we rely on this to determine the purchase information) "consumptionState ":Integer, "Invalid payload ":String}
Initiate a GET request to GoogleApi with the access_token parameter. The Java code is as follows:

Private static Map <String, String> cacheToken = null; // sets a static variable to determine whether the access_token expires. public static GooglePlayBuyEntity getInfoFromGooglePlayServer (String packageName, String productId, String purchaseToken) {if (null! = CacheToken) {Long expires_in = Long. valueOf (cacheToken. get ("expires_in"); // validity period Long create_time = Long. valueOf (cacheToken. get ("create_time"); // access_token creation time Long now_time = (new Date (). getTime ()/1000; if (now_time> (create_time + expires_in-300) {// retrieve access_tokencacheToken = getAccessToken () five minutes in advance ();}} else {cacheToken = getAccessToken ();} String access_token = cacheToken. get ("access_to Ken "); GooglePlayBuyEntity buyEntity = null; try {/** this is the latest API for writing this blog, version v2. * Https://www.googleapis.com/androidpublisher/v2/applications/?packagename} */purchases/products/{productId}/tokens/{purchaseToken }? Access_token = {access_token} */String url = "https://www.googleapis.com/androidpublisher/v2/applications"; StringBuffer getURL = new StringBuffer (); getURL. append (url); getURL. append ("/" + packageName); getURL. append ("/purchases/products"); getURL. append ("/" + productId); getURL. append ("/tokens/" + purchaseToken); getURL. append ("? Access_token = "+ access_token); URL urlObtainOrder = new URL (getURL. toString (); HttpURLConnection connectionObtainOrder = (HttpURLConnection) urlObtainOrder. openConnection (); connectionObtainOrder. setRequestMethod ("GET"); connectionObtainOrder. setDoOutput (true); // if the authentication is successful if (connectionObtainOrder. getResponseCode () = HttpURLConnection. HTTP_ OK) {StringBuilder sbLines = new StringBuilder (""); BufferedRe Ader reader = new BufferedReader (new InputStreamReader (connectionObtainOrder. getInputStream (), "UTF-8"); String strLine = ""; while (strLine = reader. readLine ())! = Null) {sbLines. append (strLine) ;}// put the retrieved information in the JSONObject so that we can directly access the desired JSONObject jo = JSONObject. fromObject (sbLines. toString (); Integer status = jo. getInt ("purchaseState"); if (status = 0) {// successfully verified buyEntity = new GooglePlayBuyEntity (); buyEntity. setConsumptionState (jo. getInt ("consumptionState"); buyEntity. setmediapayload (jo. getString ("payload"); buyEntity. setKind (jo. getString ("kind"); buyEntity. setPurchaseState (status); buyEntity. setPurchaseTimeMillis (jo. getLong ("purchaseTimeMillis");} else {// invalid buyEntity = new GooglePlayBuyEntity (); buyEntity. setPurchaseState (status); logger.info ("check failed from GooglePlay bill because purchaseStatus is" + status) ;}} catch (Exception e) {e. printStackTrace (); buyEntity = new GooglePlayBuyEntity (); buyEntity. setPurchaseState (-1);} return buyEntity ;}

This is the end of writing. If you have any questions, you can leave a message. In two days, I will write another article about ios app payment. The blog on the purchase information verification of the AppStore in the Apple Store is of the same nature.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.