简体   繁体   English

如何在 Android 中使用“OAuth 2.0”实现“使用 LinkedIn 登录”

[英]How to implement "Login with LinkedIn" with "OAuth 2.0" in Android

In OAuth1.0 "Login with Linkedin" Working fine but before few days Linkedin make some changes in their policy, please refer below link for more detail, https://engineering.linkedin.com/blog/2018/12/developer-program-updates在OAuth1.0“使用Linkedin登录”工作正常但几天前Linkedin对其政策进行了一些更改,请参阅以下链接以获取更多详细信息, https://engineering.linkedin.com/blog/2018/12/developer-program -更新

I also tried some GitHub example and other reference but unfortunately not work for me, I also tried below link but it did not fulfill the exact requirement.我也尝试了一些 GitHub 示例和其他参考,但不幸的是对我不起作用,我也尝试了下面的链接,但它没有满足确切的要求。

Oauth 2.0 authorization for LinkedIn in Android Android中LinkedIn的Oauth 2.0授权

You can also refer below link, may it give some result, I also know Linkedin SDK not work here as they declared here, https://developer.linkedin.com/docs/android-sdk We have to call manual URL and open into Webview.你也可以参考下面的链接,它可能会给出一些结果,我也知道 Linkedin SDK 在这里不起作用,因为他们在这里声明, https://developer.linkedin.com/docs/android-sdk我们必须调用手动 URL 并打开网络视图。

https://docs.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/sign-in-with-linkedin?context=linkedin/consumer/context https://docs.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/sign-in-with-linkedin?context=linkedin/consumer/context

I also check 3-4 apps which earlier had LinkedIn support for authentication but now they removed it but I check one app namely "Nuzzel" in that I found Linked in authentication and it's working fine so it means there is some way to do it properly.我还检查了 3-4 个早期支持 LinkedIn 身份验证的应用程序,但现在他们删除了它,但我检查了一个名为“Nuzzel”的应用程序,因为我发现 Linked in authentication 并且它工作正常,所以这意味着有一些方法可以正确地做到这一点. Nuzzel App Link:- https://play.google.com/store/apps/details?id=com.nuzzel.android&hl=en_GB Nuzzel 应用链接:- https://play.google.com/store/apps/details?id=com.nuzzel.android&hl=en_GB

Thanks谢谢

After a little effort I got it working, but implementing it every time you start a new project will waste a lot of time.经过一些努力,我让它工作了,但是每次开始一个新项目时都实施它会浪费很多时间。

So I created a light weight library for the same.所以我为此创建了一个轻量级的

Just add the dependency to your app level build.gradle file只需将依赖项添加到您的应用程序级build.gradle文件中

dependencies {
    implementation 'com.shantanudeshmukh:linkedinsdk:1.0.0'
}

Initiate Login Request.发起登录请求。

LinkedInBuilder.getInstance(MainActivity.this)
        .setClientID("<YOUR_CLIENT_ID_HERE>")
        .setClientSecret("<YOUR_CLIENT_SECRET_HERE>")
        .setRedirectURI("<YOUR_REDIRECT_URL_HERE>")
        .authenticate(LINKEDIN_REQUEST_CODE);

Handle the response:处理响应:

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == LINKEDIN_REQUEST_CODE && data != null) {
        if (resultCode == RESULT_OK) {
            //Successfully signed in
            LinkedInUser user = data.getParcelableExtra("social_login");

            //acessing user info
            Log.i("LinkedInLogin", user.getFirstName());

        } else {

            if (data.getIntExtra("err_code", 0) == LinkedInBuilder.ERROR_USER_DENIED) {
                //Handle : user denied access to account

            } else if (data.getIntExtra("err_code", 0) == LinkedInBuilder.ERROR_FAILED) {
                    
                //Handle : Error in API : see logcat output for details
                Log.e("LINKEDIN ERROR", data.getStringExtra("err_message"));
            }
        }
    }
}

I'm using this library in multiple production apps, so I'll try to keep it as updated as possible.我在多个生产应用程序中使用这个库,所以我会尽量保持更新。 You can find other details here .您可以在此处找到其他详细信息。

I created a small library to implement LinkedIn Authentication via OAuth2我创建了一个小型库来通过 OAuth2 实现 LinkedIn 身份验证

Library - https://github.com/Sumudu-Sahan/LinkedInManager图书馆 - https://github.com/Sumudu-Sahan/LinkedInManager

Steps脚步

  1. Add the below maven dependency to your project level build.gradle file将以下 maven 依赖项添加到您的项目级build.gradle文件中

    allprojects { repositories { ... maven { url 'https://jitpack.io' } } }

  2. add the below maven dependency to your app level build.gradle file将以下 maven 依赖项添加到您的应用程序级build.gradle文件中

    dependencies { implementation 'com.github.Sumudu-Sahan:LinkedInManager:1.00.02' }

  3. Inherit your activity, fragment from LinkedInManagerResponse继承您的活动,来自LinkedInManagerResponse片段

    public class MainActivity extends AppCompatActivity implements LinkedInManagerResponse

  4. Initiate the LinkedInRequestManager object instance for login process启动LinkedInRequestManager对象实例进行登录过程

    LinkedInRequestManager linkedInRequestManager = new LinkedInRequestManager(Activity, LinkedInManagerResponse, "CLIENT ID", "CLIENT SECRET", "REDIRECTION URL");

  5. Start Authenticate with below statement使用以下语句开始身份验证

linkedInRequestManager.showAuthenticateView(LinkedInRequestManager.MODE_BOTH_OPTIONS);

Available Modes可用模式

LinkedInRequestManager.MODE_EMAIL_ADDRESS_ONLY
LinkedInRequestManager.MODE_LITE_PROFILE_ONLY
LinkedInRequestManager.MODE_BOTH_OPTIONS

Here is my code, to implement sign in with "0Auth2.0"这是我的代码,使用“0Auth2.0”实现登录

class NewLinkedInIntegration extends Activity {

    private static final String API_KEY = "your client id";
    private static final String SECRET_KEY = "your secret key";
    private static final String STATE = "DCEeFWf45A53sdfKef424";

    private static final String REDIRECT_URI = "your url";
    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 = "=";

    String profileUrl = "https://api.linkedin.com/v2/me?projection=(id,firstName,lastName,profilePicture(displayImage~:playableStreams))";
    String accessToken;
    String linkedInUserEmailAddress;
    SharedPreferences sharedPreferences;
    String emailAddress = "https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))";
    private WebView webView;
    TransparentDialog mProgressBarHandler;
    private ProgressDialog pd;
    String deviceId, location, country;
    String linkedInUserId, linkedInUserFirstName, linkedInUserLastName, linkedInUserProfile;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_linked);
        //get the webView from the layout
        webView = (WebView) findViewById(R.id.main_activity_web_view);
        deviceId = getIntent().getStringExtra("deviceId");
        location = getIntent().getStringExtra("location");
        country = getIntent().getStringExtra("country");
        //Request focus for the webview
        webView.requestFocus(View.FOCUS_DOWN);
        webView.clearHistory();
        webView.clearCache(true);
        sharedPreferences = MyApplication.preference;
        pd = ProgressDialog.show(this, "", "Loadingg...", true);
        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;
            }
        });
        String authUrl = getAuthorizationUrl();
        Log.i("Authorize", "Loading Auth Url: " + authUrl);
        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 + "&scope=r_liteprofile%20r_emailaddress%20w_member_social";
    }


    private class PostRequestAsyncTask extends AsyncTask<String, Void, Boolean> {

        @Override
        protected void onPreExecute() {
            pd = ProgressDialog.show(NewLinkedInIntegration.this, "", "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());
                            JSONObject resultJson = new JSONObject(result);
                            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");
                                Calendar calendar = Calendar.getInstance();
                                calendar.add(Calendar.SECOND, expiresIn);
                                long expireDate = calendar.getTimeInMillis();
                                SharedPreferences preferences = NewLinkedInIntegration.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) {
                SharedPreferences preferences = NewLinkedInIntegration.this.getSharedPreferences("user_info", 0);
                accessToken = preferences.getString("accessToken", null);
                try {
                    if (accessToken != null) {
                        new GetProfileRequestAsyncTask().execute(profileUrl);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

    public void sendGetRequest(String urlString, String accessToken) throws Exception {
        URL url = new URL(urlString);
        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
        con.setRequestMethod("GET");
        con.setRequestProperty("Authorization", "Bearer " + accessToken);
        con.setRequestProperty("cache-control", "no-cache");
        con.setRequestProperty("X-Restli-Protocol-Version", "2.0.0");
        BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
        StringBuilder jsonString = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            jsonString.append(line);
        }
        JSONObject jsonObject = new JSONObject(jsonString.toString());
        Log.d("Complete json object", jsonObject.toString());
        try {
            linkedInUserId = jsonObject.getString("id");
            String country = jsonObject.getJSONObject("firstName").getJSONObject("preferredLocale").getString("country");
            String language = jsonObject.getJSONObject("firstName").getJSONObject("preferredLocale").getString("language");
            String getFirstnameKey = language + "_" + country;
            linkedInUserFirstName = jsonObject.getJSONObject("firstName").getJSONObject("localized").getString(getFirstnameKey);
            linkedInUserLastName = jsonObject.getJSONObject("firstName").getJSONObject("localized").getString(getFirstnameKey);
            linkedInUserProfile = jsonObject.getJSONObject("profilePicture").getJSONObject("displayImage~").getJSONArray("elements").getJSONObject(0).getJSONArray("identifiers").getJSONObject(0).getString("identifier");

        } catch (JSONException e) {
            e.printStackTrace();
        }

    }

    private void sendGetRequestForEmail(String urlString, String accessToken) throws Exception {
        URL url = new URL(urlString);
        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
        con.setRequestMethod("GET");
        con.setRequestProperty("Authorization", "Bearer " + accessToken);
        con.setRequestProperty("cache-control", "no-cache");
        con.setRequestProperty("X-Restli-Protocol-Version", "2.0.0");
        BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
        StringBuilder jsonString = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            jsonString.append(line);
        }
        JSONObject jsonObject = new JSONObject(jsonString.toString());
        linkedInUserEmailAddress = jsonObject.getJSONArray("elements").getJSONObject(0).getJSONObject("handle~").getString("emailAddress");
        Log.d("email json object", jsonObject.toString());
        sendRequestToServerForLinkwedInIntegration();


    }

    public void sendRequestToServerForLinkwedInIntegration() {

        if (AppUtils.isInternetOn(NewLinkedInIntegration.this)) {

            JSONObject userJsonObject = new JSONObject();
            try {
                userJsonObject.put(NetworkKeys.EMAIL, linkedInUserEmailAddress);
                userJsonObject.put(NetworkKeys.USERNAME, linkedInUserFirstName + " " + linkedInUserLastName);
                userJsonObject.put(NetworkKeys.CONTACTNO, "");
                userJsonObject.put(NetworkKeys.UID, linkedInUserId);
                userJsonObject.put(NetworkKeys.PROVIDER, "LinkedIn");
                userJsonObject.put(NetworkKeys.IMAGE, linkedInUserProfile);
                userJsonObject.put(NetworkKeys.DEVICE_TOKEN, deviceId);
                userJsonObject.put(NetworkKeys.LOCATION, location);
                userJsonObject.put(NetworkKeys.COUNTRY, country);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            String url = Constants.WebServices.SOCIAL_MEDIA_LOGIN;
            CallWebService.getInstance(NewLinkedInIntegration.this, true).hitJSONObjectVolleyWebServicemanageclubdetailsWithoutAccessToken(Request.Method.POST, url, deviceId, userJsonObject, new CallBackInterfaceVolley() {
                @Override
                public void onJsonObjectSuccess(JSONObject object) {
                    pd.dismiss();
                    try {
                        boolean success = object.getBoolean(NetworkKeys.SUCCESS);

                        if (success) {
                            JSONObject userInfoJsonObject = object.getJSONObject(NetworkKeys.USERJSONOBJECT);
                            String userId = userInfoJsonObject.getString(NetworkKeys.SIGN_IN_USERID);
                            String userEmail = userInfoJsonObject.getString(NetworkKeys.SIGN_IN_USER_EMAIL);
                            String userImage = userInfoJsonObject.getString(NetworkKeys.SIGN_IN_USER_IMAGE);
                            String userName = userInfoJsonObject.getString(NetworkKeys.SIGN_IN_USER_NAME);
                            String userCity = userInfoJsonObject.getString(NetworkKeys.USER_CITY);
                            String contactNo = userInfoJsonObject.getString(NetworkKeys.CONTACT_NO);
                            String userCountry = userInfoJsonObject.getString(NetworkKeys.USER_COUNTRY);
                            String isNotificationOn = userInfoJsonObject.getString(NetworkKeys.ISNOTIFICATION);
                            String userLocation = userInfoJsonObject.getString(NetworkKeys.SIGN_IN_USER_LOCATION);
                            String signInUserType = userInfoJsonObject.getString(NetworkKeys.SIGN_IN_USER_PROVIDER);
                            String userAuthToken = userInfoJsonObject.getString(NetworkKeys.SIGN_IN_USER_AUTHTOKEN);
                            SharedPreferences.Editor editor = sharedPreferences.edit();
                            editor.putString(NetworkKeys.SIGN_IN_USERID, userId);
                            editor.putString(NetworkKeys.SIGN_IN_USER_EMAIL, userEmail);
                            editor.putString(NetworkKeys.SIGN_IN_USER_IMAGE, userImage);
                            editor.putString(NetworkKeys.SIGN_IN_USER_NAME, userName);
                            editor.putString(NetworkKeys.USER_CITY, userCity);
                            editor.putString(NetworkKeys.USER_COUNTRY, userCountry);
                            editor.putString(NetworkKeys.SIGN_IN_USER_MOBILE, contactNo);
                            editor.putString(NetworkKeys.SIGN_IN_USER_LOCATION, userLocation);
                            editor.putString(NetworkKeys.SIGN_IN_USER_PROVIDER, signInUserType);
                            editor.putString(NetworkKeys.ISNOTIFICATION, isNotificationOn);
                            editor.putString(NetworkKeys.SIGN_IN_USER_AUTHTOKEN, userAuthToken);
                            editor.putBoolean(NetworkKeys.IS_USER_LOGIN_FROM_SOCIAL_MEDIA, true);
                            editor.putBoolean(NetworkKeys.SIGN_IN_USER_SUCCESSFULLY, true);
                            editor.apply();
                            Intent intent = new Intent(NewLinkedInIntegration.this, CardSelctionActivity.class);
                            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
                            startActivity(intent);
                            finish();
                        } else {
                            pd.dismiss();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onJsonArrarSuccess(JSONArray array) {

                }

                @Override
                public void onFailure(String str) {
                    pd.dismiss();
                }
            });
        } else {
            AppUtils.showToast(NewLinkedInIntegration.this, getResources().getString(R.string.internet_connection));
        }
    }


    private class GetProfileRequestAsyncTask extends AsyncTask<String, Void, JSONObject> {

        @Override
        protected void onPreExecute() {
            pd = ProgressDialog.show(NewLinkedInIntegration.this, "", "Loading..", true);
        }

        @Override
        protected JSONObject doInBackground(String... urls) {
            if (urls.length > 0) {
                try {
                    sendGetRequest(profileUrl, accessToken);
                    sendGetRequestForEmail(emailAddress, accessToken);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return null;
        }

        @Override
        protected void onPostExecute(JSONObject data) {
            if (pd != null && pd.isShowing()) {
                pd.dismiss();
            }
            if (data != null) {

                try {
                    String welcomeTextString = String.format("Welcome %1$s %2$s, You are a %3$s", data.getString("firstName"), data.getString("lastName"), data.getString("headline"));

                } catch (JSONException e) {
                    Log.e("Authorize", "Error Parsing json " + e.getLocalizedMessage());
                }
            }
        }

    }
}

If you want further assistance go to below link explained how to sign in with Linkedin with auth 2.0.如果您需要进一步的帮助,请转到以下链接,该链接解释了如何使用 auth 2.0 登录 Linkedin。 Have a look看一看

linkedin integration with oauth20 -v2-in-complete implementation ain android Linkedin 与 oauth20 的集成 -v2-in-complete 实现 ain android

Inspired by @Shantanu, I've restructured/updated his "unofficial" SDK for Android, you can use it from [this GitHub repo]( https://github.com/AbdAllahAbdElFattah13/LinkedIn-SDK-Android .受@Shantanu 的启发,我重新构建/更新了他的“非官方”Android SDK,您可以从 [this GitHub repo]( https://github.com/AbdAllahAbdElFattah13/LinkedIn-SDK-Android )使用它。

It's now Kotlin based and follows clean architecture principles for better understanding and modifications.它现在基于 Kotlin 并遵循简洁的架构原则,以便更好地理解和修改。

We also use it in our production apps, so it should be working fine.我们也在我们的生产应用程序中使用它,所以它应该可以正常工作。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM