#안드로이드 Third party 로그인 연동 2(네이버 연동)

2019. 9. 12. 21:15 개발 이야기/android

 

오늘은 네이버 로그인 API 연동을 해볼거에요!

네이버의 경우에는 CLIENT_IDSECRET 문자열이 필요한데요!

 

네이버 개발자 센터에 앱을 등록하신 후 해당 문자열을 아래와 같이 붙여넣으주면 됩니다!

 

https://developers.naver.com/main/

public class NaverAuth extends AppCompatActivity {

    @SuppressLint("StaticFieldLeak")
    private static NaverAuth instance;
    private static APIInterface apiInterface;
    private static OAuthLogin mOAuthLoginInstance;
    @SuppressLint("StaticFieldLeak")
    private static Context mContext;

    /**
     * client 정보를 넣어준다.
     */
    private static String OAUTH_CLIENT_ID = "클라이언트 아이디";
    private static String OAUTH_CLIENT_SECRET = "시크릿 문자열";
    private static String OAUTH_CLIENT_NAME = "네이버 아이디로 로그인";


    public static NaverAuth getInstance(Context context) {
        mContext = context;
        if (instance == null) {
            instance = new NaverAuth();
        }
        mOAuthLoginInstance = OAuthLogin.getInstance();
        if (!OAuthLoginState.NEED_LOGIN.equals(OAuthLogin.getInstance().getState(context)) &&
                !OAuthLoginState.NEED_INIT.equals(mOAuthLoginInstance.getState(context))) {
            Dlog.Companion.d("네이버 로그인 되어 있음");
            new RequestApiTask(context).execute();  // 서버로 정보 전송 함수
        }
        return instance;
    }

 

다른 SNS 로그인과 마찬가지로 따로 클래스를 빼서 

싱글톤 패턴을 적용시켰는데요!

 

로그에서 보이는 바와 같이 로그인이 되어있는 상태면 바로 서버로 필요한 정보를 전송하도록 로직을 구성했습니다.

 

다음은 로그인을 시도하는 로직인데요

 

아래와 같이 init 후에 

startOauthLoginActivity 함수를 실행시켜주면 

 

네이버 앱과 연동이 되면서 로그인하는 창이 뜨고 자동으로 로그인이 됩니다!

    public void Login(Context context) {
        Dlog.Companion.d("네이버 로그인 실행");
        mContext = context;
        mOAuthLoginInstance = OAuthLogin.getInstance();
        mOAuthLoginInstance.showDevelopersLog(true);
        mOAuthLoginInstance.init(mContext, OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET, OAUTH_CLIENT_NAME);
        mOAuthLoginInstance.startOauthLoginActivity((Activity) mContext, mOAuthLoginHandler);
    }

로그인이 된 후에 는 mOAuthLoginHandler로 다음 액션을 던져주는데요!

 

핸들러는 이렇게 생겼습니다

로그인 성공 실패로 아래와 같이 나눠서 성공 시에는 RequestApiTask를 실행하도록 했습니다!

    @SuppressLint("HandlerLeak")
    private OAuthLoginHandler mOAuthLoginHandler = new OAuthLoginHandler() {
        @Override
        public void run(boolean success) {
            if (success) {
                Dlog.Companion.d("네이버 로그인 성공");
                String accessToken = mOAuthLoginInstance.getAccessToken(mContext);
                Dlog.Companion.d("accessToke Value " + accessToken);
                String refreshToken = mOAuthLoginInstance.getRefreshToken(mContext);
                Dlog.Companion.d("액세스 토큰 : " + accessToken);
                Dlog.Companion.d("refreshToken 토큰 : " + refreshToken);

                Dlog.Companion.d("getState 상태 : " + mOAuthLoginInstance.getState(mContext).toString());
                new RequestApiTask(mContext).execute();
            } else {
                String errorCode = mOAuthLoginInstance.getLastErrorCode(mContext).getCode();
                String errorDesc = mOAuthLoginInstance.getLastErrorDesc(mContext);
                Dlog.Companion.d("네이버 인증 에러 : errorCode:" + errorCode + ", errorDesc:" + errorDesc);
            }
        }

    };

 

다음은 로그아웃 로직인데요!

    public static void signOut(Context context) {
        mOAuthLoginInstance = OAuthLogin.getInstance();
        String loginState = mOAuthLoginInstance.getState(context).toString();
        if (!loginState.equals("NEED_LOGIN")) {
            Dlog.Companion.d("네이버 로그아웃");
            mOAuthLoginInstance.logout(context);
            RedirectActivity.getInstance().signOutAfterLoginActivity(context);
        } else {
            Dlog.Companion.d("네이버 세션 없음");
        }
    }

로그아웃은 간단하게 mOatyhLoginInstance.logout으로 처리할 수 있습니다 

 

그리고 로그아웃이 된 다음에 액션도 만들어서 넣어주어야겠죠!?

 

 

다음은 연결 해제. 즉 탈퇴 로직입니다

탈퇴하게 되면은 사용자 계정과 앱의 연결을 끊고 성공 시에 서버에 저장됐던 정보도 지워주려고

deleteAccount 함수를 실행시키는 모습입니다!

이 함수는 각자 개발 콘셉트에 맞게 구현되어야겠죠??

    public static void Unlink(Context context) {
        Dlog.Companion.d("네이버 언링크");
        if (!OAuthLoginState.NEED_LOGIN.equals(OAuthLogin.getInstance().getState(context))) {
            new DeleteTokenTask().execute();
            requestModule.deleteAccount(context);
        } else {
            RedirectActivity.getInstance().signOut(context);
        }
    }

    private static class DeleteTokenTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... params) {
            boolean isSuccessDeleteToken = mOAuthLoginInstance.logoutAndDeleteToken(mContext);

            Dlog.Companion.d("");
            if (!isSuccessDeleteToken) {
                // 서버에서 token 삭제에 실패했어도 클라이언트에 있는 token 은 삭제되어 로그아웃된 상태이다
                // 실패했어도 클라이언트 상에 token 정보가 없기 때문에 추가적으로 해줄 수 있는 것은 없음
                Dlog.Companion.d("errorCode:" + mOAuthLoginInstance.getLastErrorCode(mContext));
                Dlog.Companion.d("errorDesc:" + mOAuthLoginInstance.getLastErrorDesc(mContext));
            }

            return null;
        }

        protected void onPostExecute(Void v) {
            Dlog.Companion.d("");
        }
    }

 

 

다음은 네이버에서 토큰을 가져오는 부분입니다.

    private static class RequestApiTask extends AsyncTask<Void, Void, StringBuffer> {
        private String token;

        RequestApiTask(Context context) {
            mContext = context;
        }

        @Override
        protected void onPreExecute() {
        }

        @Override
        protected StringBuffer doInBackground(Void... params) {
            OAuthLogin mOAuthLoginInstance = OAuthLogin.getInstance();
            if (OAuthLoginState.NEED_REFRESH_TOKEN.equals(mOAuthLoginInstance.getState(mContext))) {  // 네이버
                Dlog.Companion.d("네이버 로그인 확인 !!!!!!!!!!!!" + mOAuthLoginInstance.getState(mContext));
                mOAuthLoginInstance.refreshAccessToken(mContext);
            }
            this.token = mOAuthLoginInstance.getAccessToken(mContext);
            String header = "Bearer " + this.token;
            try {
                final String apiURL = "https://openapi.naver.com/v1/nid/me";
                URL url = new URL(apiURL);
                HttpURLConnection con = (HttpURLConnection) url.openConnection();
                con.setRequestMethod("GET");
                con.setRequestProperty("Authorization", header);
                int responseCode = con.getResponseCode();

                BufferedReader br = new BufferedReader(new InputStreamReader(
                        responseCode == 200 ? con.getInputStream() : con.getErrorStream()));

                String inputLine;
                StringBuffer response = new StringBuffer();
                while ((inputLine = br.readLine()) != null) {
                    response.append(inputLine);
                }

                br.close();
                return response;

            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

        protected void onPostExecute(StringBuffer content) {
            super.onPostExecute(content);

            try {
                JSONObject jsonObject = new JSONObject(String.valueOf(content));
                JSONObject response = jsonObject.getJSONObject("response");
                String id = response.getString("id");
                String email;
                try {
                    email = response.getString("email");
                } catch (Exception e) {
                    email = null;
                }

//                리퀘스트 변경
                Request(mContext, this.token, id, email);


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

 

 

여기서 중요한 것은 이 부분인데요

네이버의 토큰은 유효기간이 1시간밖에 안되기 때문에

주기적으로 갱신을 시켜줘야 합니다

유효기간이 만료되면 OAuthLoginState가  NEED_REFRESH_TOKEN으로 변경되는데

이 부분에서 갱신을 아래와 같이 해주지 않는다면! 탈퇴 같은 기능을 사용할 수 없게 됩니다!

저는 이 부분에서 많이 헤매었던 기억이 있습니다

if (OAuthLoginState.NEED_REFRESH_TOKEN.equals(mOAuthLoginInstance.getState(mContext))) {  // 네이버
    Dlog.Companion.d("네이버 로그인 확인 !!!!!!!!!!!!" + mOAuthLoginInstance.getState(mContext));
    mOAuthLoginInstance.refreshAccessToken(mContext);
}

 

 

이렇게 해서 오늘은 네이버 로그인 연동에 대해서 알아보았습니다