Oauth 2.0 authorization for LinkedIn in Android
Oauth2.0 authentication for LinkedIN.
Step 1:
- Register your app with linkedIn by following this document. And get your api_key and api_secret.
Step 2:
MainActivity:
public class MainActivity extends Activity {
/*CONSTANT FOR THE AUTHORIZATION PROCESS*/
/****FILL THIS WITH YOUR INFORMATION*********/
//This is the public api key of our application
private static final String API_KEY = "YOUR_API_KEY";
//This is the private api key of our application
private static final String SECRET_KEY = "YOUR_API_SECRET";
//This is any string we want to use. This will be used for avoiding CSRF attacks. You can generate one here: http://strongpasswordgenerator.com/
private static final String STATE = "E3ZYKC1T6H2yP4z";
//This is the url that LinkedIn Auth process will redirect to. We can put whatever we want that starts with http:// or https:// .
//We use a made up url that we will intercept when redirecting. Avoid Uppercases.
private static final String REDIRECT_URI = "http://com.amalbit.redirecturl";
/*********************************************/
//These are constants used for build the urls
private static final String AUTHORIZATION_URL = "https://www.linkedin.com/uas/oauth2/authorization";
private static final String ACCESS_TOKEN_URL = "https://www.linkedin.com/uas/oauth2/accessToken";
private static final String SECRET_KEY_PARAM = "client_secret";
private static final String RESPONSE_TYPE_PARAM = "response_type";
private static final String GRANT_TYPE_PARAM = "grant_type";
private static final String GRANT_TYPE = "authorization_code";
private static final String RESPONSE_TYPE_VALUE ="code";
private static final String CLIENT_ID_PARAM = "client_id";
private static final String STATE_PARAM = "state";
private static final String REDIRECT_URI_PARAM = "redirect_uri";
/*---------------------------------------*/
private static final String QUESTION_MARK = "?";
private static final String AMPERSAND = "&";
private static final String EQUALS = "=";
private WebView webView;
private ProgressDialog pd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//get the webView from the layout
webView = (WebView) findViewById(R.id.main_activity_web_view);
//Request focus for the webview
webView.requestFocus(View.FOCUS_DOWN);
//Show a progress dialog to the user
pd = ProgressDialog.show(this, "", this.getString(R.string.loading),true);
//Set a custom web view client
webView.setWebViewClient(new WebViewClient(){
@Override
public void onPageFinished(WebView view, String url) {
//This method will be executed each time a page finished loading.
//The only we do is dismiss the progressDialog, in case we are showing any.
if(pd!=null && pd.isShowing()){
pd.dismiss();
}
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String authorizationUrl) {
//This method will be called when the Auth proccess redirect to our RedirectUri.
//We will check the url looking for our RedirectUri.
if(authorizationUrl.startsWith(REDIRECT_URI)){
Log.i("Authorize", "");
Uri uri = Uri.parse(authorizationUrl);
//We take from the url the authorizationToken and the state token. We have to check that the state token returned by the Service is the same we sent.
//If not, that means the request may be a result of CSRF and must be rejected.
String stateToken = uri.getQueryParameter(STATE_PARAM);
if(stateToken==null || !stateToken.equals(STATE)){
Log.e("Authorize", "State token doesn't match");
return true;
}
//If the user doesn't allow authorization to our application, the authorizationToken Will be null.
String authorizationToken = uri.getQueryParameter(RESPONSE_TYPE_VALUE);
if(authorizationToken==null){
Log.i("Authorize", "The user doesn't allow authorization.");
return true;
}
Log.i("Authorize", "Auth token received: "+authorizationToken);
//Generate URL for requesting Access Token
String accessTokenUrl = getAccessTokenUrl(authorizationToken);
//We make the request in a AsyncTask
new PostRequestAsyncTask().execute(accessTokenUrl);
}else{
//Default behaviour
Log.i("Authorize","Redirecting to: "+authorizationUrl);
webView.loadUrl(authorizationUrl);
}
return true;
}
});
//Get the authorization Url
String authUrl = getAuthorizationUrl();
Log.i("Authorize","Loading Auth Url: "+authUrl);
//Load the authorization URL into the webView
webView.loadUrl(authUrl);
}
/**
* Method that generates the url for get the access token from the Service
* @return Url
*/
private static String getAccessTokenUrl(String authorizationToken){
return ACCESS_TOKEN_URL
+QUESTION_MARK
+GRANT_TYPE_PARAM+EQUALS+GRANT_TYPE
+AMPERSAND
+RESPONSE_TYPE_VALUE+EQUALS+authorizationToken
+AMPERSAND
+CLIENT_ID_PARAM+EQUALS+API_KEY
+AMPERSAND
+REDIRECT_URI_PARAM+EQUALS+REDIRECT_URI
+AMPERSAND
+SECRET_KEY_PARAM+EQUALS+SECRET_KEY;
}
/**
* Method that generates the url for get the authorization token from the Service
* @return Url
*/
private static String getAuthorizationUrl(){
return AUTHORIZATION_URL
+QUESTION_MARK+RESPONSE_TYPE_PARAM+EQUALS+RESPONSE_TYPE_VALUE
+AMPERSAND+CLIENT_ID_PARAM+EQUALS+API_KEY
+AMPERSAND+STATE_PARAM+EQUALS+STATE
+AMPERSAND+REDIRECT_URI_PARAM+EQUALS+REDIRECT_URI;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private class PostRequestAsyncTask extends AsyncTask<String, Void, Boolean>{
@Override
protected void onPreExecute(){
pd = ProgressDialog.show(MainActivity.this, "", MainActivity.this.getString(R.string.loading),true);
}
@Override
protected Boolean doInBackground(String... urls) {
if(urls.length>0){
String url = urls[0];
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpost = new HttpPost(url);
try{
HttpResponse response = httpClient.execute(httpost);
if(response!=null){
//If status is OK 200
if(response.getStatusLine().getStatusCode()==200){
String result = EntityUtils.toString(response.getEntity());
//Convert the string result to a JSON Object
JSONObject resultJson = new JSONObject(result);
//Extract data from JSON Response
int expiresIn = resultJson.has("expires_in") ? resultJson.getInt("expires_in") : 0;
String accessToken = resultJson.has("access_token") ? resultJson.getString("access_token") : null;
Log.e("Tokenm", ""+accessToken);
if(expiresIn>0 && accessToken!=null){
Log.i("Authorize", "This is the access Token: "+accessToken+". It will expires in "+expiresIn+" secs");
//Calculate date of expiration
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, expiresIn);
long expireDate = calendar.getTimeInMillis();
////Store both expires in and access token in shared preferences
SharedPreferences preferences = MainActivity.this.getSharedPreferences("user_info", 0);
SharedPreferences.Editor editor = preferences.edit();
editor.putLong("expires", expireDate);
editor.putString("accessToken", accessToken);
editor.commit();
return true;
}
}
}
}catch(IOException e){
Log.e("Authorize","Error Http response "+e.getLocalizedMessage());
}
catch (ParseException e) {
Log.e("Authorize","Error Parsing Http response "+e.getLocalizedMessage());
} catch (JSONException e) {
Log.e("Authorize","Error Parsing Http response "+e.getLocalizedMessage());
}
}
return false;
}
@Override
protected void onPostExecute(Boolean status){
if(pd!=null && pd.isShowing()){
pd.dismiss();
}
if(status){
//If everything went Ok, change to another activity.
Intent startProfileActivity = new Intent(MainActivity.this, ProfileActivity.class);
MainActivity.this.startActivity(startProfileActivity);
}
}
};
}
And the xmlLayout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<WebView
android:id="@+id/main_activity_web_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
The token is saved in the sharedpreference file.
Simple android project repo here in github.
LinkedIn oauth 2.0 for Android
That is not the correct access token that you are sending. See this example get access token from linkedIn
How do I get the r_fullprofile permission for my Linked In OAuth 2.0 client application?
You can't easily find how to get access to r_fullprofile
because this is not available except is very limited circumstances, which are tied to those specific Enterprise partnership programs. Even in those cases, we don't always give this out. It depends on the specific use case.
Those partnerships are for mature/established companies, so the expectation is you wouldn't be changing of your site or domain name. (Although, you can add/edit/delete items app details, such as your redirect_uri
.)
At this time, you can get r_liteprofile
as part of the standard LinkedIn API offering. You can use to implement Sign In with LinkedIn on your site. I understand this is far less data than the full profile.
This probably not what you want to hear. However, given the evident frustration you had in finding the information on the developer site and the time you took to write this all up, I wanted to take the time to help clarify things for you and anyone else who comes across this thread. I'll also ask the team to see how we can improve the site and/or add this to the FAQ.
Migrate LinkedIn to API v2
Unfortunately, it appears that the mobile and javascript SDKs have been deprecated. See here: https://engineering.linkedin.com/blog/2018/12/developer-program-updates
SDKs: Our JavaScript and Mobile Software Development Kits (SDKs) will stop working. Developers will need to migrate to using OAuth 2.0 directly from their apps.
To the best that I can tell, since the OAuth flow is available in the browser only, you'll now need to kick to web to do auth on mobile.
Related Topics
Why Getspeed() Always Return 0 on Android
Android: Setselection Having No Effect on Spinner
Parse JSON Array Response Using Retrofit & Gson
Android Studio: Gradle: Error: Cannot Find Symbol Variable
Android Mediarecorder - "Start Failed: -19"
Streaming Audio from a Url in Android Using Mediaplayer
Android Preferences: How to Load the Default Values When the User Hasn't Used the Preferences-Screen
Android: Last Line of Textview Cut Off
How to Restart Adb Manually from Android Studio
Oauth 2.0 Authorization for Linkedin in Android
How to Set Text to View from Drawer Header Layout in Navigation Drawer Without Inflating View
How to Default to Numeric Keyboard on Edittext Without Forcing Numeric Input
Android Intent.Getstringextra() Returns Null
Comparing Two Times in Android