스프링 부트 - 트위터 로그인

jinvicky·2024년 1월 30일
0
post-thumbnail

Intro

지금까지 해본 로그인은 네이버와 카카오였다.
하지만 내가 벤치마킹한 크레페라는 사이트는 트위터를
왜냐하면 관심 유저들이 거의 트위터를 쓰기 때문이다.
그래서 나도 추가해보았다. 아래는 과정에 대한 모든 시행착오를 담았다.
네이버와 카카오에 비해 참고 자료는 적지만, 할 수 있다!

애플리케이션 생성

트위터 디벨로퍼 사이트에 들어가서 애플리케이션을 하나 만든다.

트위터 계정이 있는 경우 카카오, 네이버 하듯이 내 애플리케이션 가서 디폴트 외에 하나 더 만들면 그만이다.

계정이 쌩으로 없는 경우 아래를 따라한다.
참고 https://flycoding.tistory.com/entry/트위터-개발자-계정-만들기

애플리케이션을 대략 만들었다면 아래와 같은 설정 정보 페이지를 볼 수 있을 것이다.

코드 적용하기

기본 베이스로 아래 사이트를 참고하면서 에러가 생기면 하나씩 고쳐나갔다.
참고 https://rohankadam965.medium.com/how-to-implement-oauth-social-login-using-twitter-spring-boot-java-part-2-acff7f4b255a

client가 아니라 Consumer다.

 TwitterConnectionFactory connectionFactory =
                new TwitterConnectionFactory(apiKey,apiSecret);
        OAuth1Operations oauthOperations = connectionFactory.getOAuthOperations();

참고 블로그에서 clientId, clientSecret라고 되어 있는데, clientId가 아니라 Consumer 부분의 key, secret을 사용해야 한다.

이 값을 사용해야 한다. 아래로 더 가면 clientId, clientSecret항목이 있는데 그거 아니다.

의존성 문제

ClassNotFoundException, NoSuchMethodsException ~

social-twitter 관련 의존성과 코드를 추가하고 프로젝트를 실행하면 다음과 같은 에러를 마주친다.
특히 두번째의 메서드가 존재하지 않는다는 예외는 의존성 주입 시 라이브러리 버전 충돌 때문이다.

그리고 social-twitter 라이브러리만으로는 부족하다.
따라서 아래 두 가지를 수정해 문제를 해결했다.

  • 의존성 버전 높이기
  • httpcore, httpclient 의존성을 추가
    *social-twitter는 1.1.2가 최신이었다.

build.gradle.kts

   //twitter
    implementation ("org.springframework.social:spring-social-twitter:1.1.2.RELEASE")
    implementation("org.apache.httpcomponents.client5:httpclient5:5.3.1")
    implementation("org.apache.httpcomponents.core5:httpcore5:5.2.4")

requestToken.getValue()

이 에러가 왜 발생했을까? requestToken 객체 자체를 String 형변환해서 요청 토큰 중복이 발생한 것으로 추정된다. (코드는 모두 위 참고 블로그 기준)

 @GetMapping("/oauth2/authorize/normal/twitter")
    public void twitterOauthLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {

        TwitterConnectionFactory connectionFactory =
                new TwitterConnectionFactory(apiKey,apiSecret);
        OAuth1Operations oauthOperations = connectionFactory.getOAuthOperations();
//        oauthOperations.toString(); //필요없다. 

        String callbackUrl = "http://localhost:8080/social/twitter";

// 틀렸습니다. 
//        OAuthToken requestToken = oauthOperations.fetchRequestToken(callbackUrl, null);
//        String authorizeUrl = oauthOperations.buildAuthorizeUrl(String.valueOf(requestToken), OAuth1Parameters.NONE);

// 맞습니다. 
		OAuthToken requestToken = oauthOperations.fetchRequestToken(callbackUrl, null);
        String token = requestToken.getValue();
        String authorizeUrl = oauthOperations.buildAuthorizeUrl(token, OAuth1Parameters.NONE);
        response.sendRedirect(authorizeUrl);
    }

주석 맞습니다를 기준으로 변경해 주었더니 통과했다.

CallbackUrl을 fetchRequestToken()에 넣어라

어째저째 콜백 url로 넘어왔더니 아래 이슈 발생;;

  • callbackUrl이 애플리케이션에서 지정한 url과 동일한지 재확인

결과적으로 아래 코드로 twitter login을 구현할 수 있다.
OauthController.java

private final TwitterApiInfo twitterApiInfo;

    
    @PostMapping("/process/twitter")
    public Map<String, Object> twitterOauthCallback (@RequestBody Map<String, Object> codeMap) {

        TwitterConnectionFactory connectionFactory = new TwitterConnectionFactory(twitterApiInfo.getApiKey(),twitterApiInfo.getApiSecret());
        OAuth1Operations oauthOperations = connectionFactory.getOAuthOperations();

        String oauthToken = String.valueOf(codeMap.get("oauthToken"));
        String oauthVerifier = String.valueOf(codeMap.get("oauthVerifier"));

        OAuthToken accessToken = oauthOperations.exchangeForAccessToken(
                new AuthorizedRequestToken(new OAuthToken(oauthToken, ""), oauthVerifier), null);

        System.out.println("Token Value:- accesstoken");
        Twitter twitter = new TwitterTemplate(twitterApiInfo.getApiKey(),
                twitterApiInfo.getApiSecret(),
                accessToken.getValue(),
                accessToken.getSecret());
        TwitterProfile profile = twitter.userOperations().getUserProfile();

        profile.getId(); // 고유 사용자 uid 느낌

        return CommonUtil.successResultMap(profile);
    }

/* 트위터 로그인, 호출시 트위터 인증 페이지로 이동 */
    @GetMapping("/sign/in/twitter")
    public void  twitterOauthLogin(HttpServletResponse response) throws IOException {
        TwitterConnectionFactory connectionFactory =
                new TwitterConnectionFactory(twitterApiInfo.getApiKey(),twitterApiInfo.getApiSecret());
        OAuth1Operations oauthOperations = connectionFactory.getOAuthOperations();

        OAuthToken requestToken = oauthOperations.fetchRequestToken(twitterApiInfo.getCallbackUrl(), null);
        String token = requestToken.getValue();
        String authorizeUrl = oauthOperations.buildAuthorizeUrl(token, OAuth1Parameters.NONE);

        response.sendRedirect(authorizeUrl);
    }

TwitterApiInfo.java

@Getter
@Setter
@Component
public class TwitterApiInfo {

    @Value("${twitter.consumerKey}")
    private String apiKey;

    @Value("${twitter.consumerSecret}")
    private String apiSecret;

    @Value("${twitter.redirectUrl}")
    private String callbackUrl;
}

여기까지는 순수하게 소셜 로그인 연동만 했다.
앞으로 DB와의 연동을 진행할 예정이다.

소셜 로그인의 공통된 고유값이 뭘까?

카카오, 네이버, 트위터 모두 공통된 unique값이 없다;;
심지어 카카오 계정이지만 이메일이 없는 계정도 있어서 에러가 발생했었다;;


TwitterProfile 클래스도 까봤더니 이메일도, 전화번호도 없어서 매우 당황했다;;

이 시점에서 내가 내린 결론은 소셜의 id값을 이용하자는 것이었다.

naver의 경우 BASE64로 id를 제공하고, 트위터는 long 타입의 id를 제공한다.
카카오는 아래 문서를 보면 이제 앱 연결과 상관없이 회원당 고유 id를 유지한다고 한다. (카카오도 로그인 또는 회원 조회 api에서 id를 얻을 수 있다.

참고 https://devtalk.kakao.com/t/topic/55164/3

profile
Front-End와 Back-End 경험, 지식을 공유합니다.

0개의 댓글