8. 페이스북 Oauth 로그인

2022. 2. 22. 20:48· 취업 준비/Spring security

1. Meta(구 Facebook) developers에 들어가서 새 앱을 만들어준다.

없음 누르고 앱 ID 아무렇게나 입력하도 만들면 된다.

 

2. 페이스북 로그인 제품 추가

웹을 누르고 넘어간다.

 

자바스크립트가 아니라 OAuth2 클라이언트로 구현할 것이기 때문에 URL만 입력하고 나머지는 넘어간다.

 

3. 설정 -> 기본 설정에 들어가서 앱 ID와 시크릿 코드를 확인한다.

4. application.yml 수정

들여쓰기를 맞춰서 id와 코드를 넣어준다.

https://developers.facebook.com/docs/facebook-login/web/permissions

 

권한 - Facebook 로그인 - 문서 - Facebook for Developers

거부된 권한 다시 요청 Facebook 로그인은 사용자가 앱과 권한을 공유하는 것을 거부할 수 있는 기능을 제공합니다. 사용자가 user_likes(좋아요)를 거부하는 경우 /me/permissions에서 부여된 권한을 확

developers.facebook.com

이 문서를 보면 scope는 이름이 public_profile로 되어있기 때문에 public_profile을 넣어줘야 한다.

 

5. loginForm 수정

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인 페이지</title>
</head>
<body>
<h1>로그인 페이지</h1>
<hr>
<form action="/login" method="POST">
	<input type="text" name="username" placeholder="Username"> <br>
	<input type="password" name="password" placeholder="Password"> <br>
	<button>로그인</button>	
</form>
<a href="/oauth2/authorization/google">구글 로그인</a>
<a href="/oauth2/authorization/facebook">페이스북 로그인</a> //추가함
<a href="/joinForm">회원가입을 아직 하지 않으셨나요?</a>
</body>
</html>

 

6. 페이스북 로그인을 클릭해본다.

제대로 로그인이 되는 것을 확인할 수 있다. 

하지만 DB에서 확인해보면 providerId가 null인 것을 알 수 있다.

왜냐하면 구글 로그인에서는 getAttribute("sub")가 있었지만 페이스북은 그 자리가 getAttribute("id")가 되어야 하기 때문이다. (나는 그래서 PrincipalOauth2UserService에서 그냥 provider만 분기처리 해서 그대로 쓰는 방식을 생각했었다.)

 

유지보수의 용이성을 위해 우리는 OAuth2UserInfo라는 인터페이스를 만들거다.

인터페이스를 만들어두면 네이버나 카카오 등의 다른 OAuth 인증 방식을 추가할 때 덜 헷갈리고 코드가 덜 복잡해진다.

package com.pure.security.config.oauth.provider;

public interface OAuth2UserInfo {
	String getProviderId();
	String getProvider();
	String getEmail();
	String getName();
}

 

OAuth2UserInfo를 구현하는 GoogleUserInfo와 FacebookUserInfo 클래스를 만든다.

package com.pure.security.config.oauth.provider;

import java.util.Map;

public class GoogleUserInfo implements OAuth2UserInfo {

	private Map<String, Object> attributes;
	
	public GoogleUserInfo(Map<String, Object> attributes) {
		this.attributes = attributes;
	}
	
	@Override
	public String getProviderId() {		
		return (String)attributes.get("sub");
	}

	@Override
	public String getProvider() {
		return "google";
	}

	@Override
	public String getEmail() {
		return (String)attributes.get("email");
	}

	@Override
	public String getName() {
		return (String)attributes.get("name");
	}

}

 

 

package com.pure.security.config.oauth.provider;

import java.util.Map;

public class FacebookUserInfo implements OAuth2UserInfo {

	private Map<String, Object> attributes;
	
	public FacebookUserInfo(Map<String, Object> attributes) {
		this.attributes = attributes;
	}
	
	@Override
	public String getProviderId() {		
		return (String)attributes.get("id");
	}

	@Override
	public String getProvider() {
		return "facebook";
	}

	@Override
	public String getEmail() {
		return (String)attributes.get("email");
	}

	@Override
	public String getName() {
		return (String)attributes.get("name");
	}

}

이를 이용하여 로그인/회원가입 로직을 다시 쓴다.

PrincipalOauth2UserService 수정

package com.pure.security.config.oauth;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service;

import com.pure.security.config.auth.PrincipalDetails;
import com.pure.security.config.oauth.provider.FacebookUserInfo;
import com.pure.security.config.oauth.provider.GoogleUserInfo;
import com.pure.security.config.oauth.provider.OAuth2UserInfo;
import com.pure.security.model.User;
import com.pure.security.repository.UserRepository;

@Service
public class PrincipalOauth2UserService extends DefaultOAuth2UserService {
	
	@Autowired
	private UserRepository userRepository;
	
	@Override
	public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
		System.out.println("userRequset.getClientRegistration: "+ userRequest.getClientRegistration()); //registrationId로 어떤 OAuth로 로그인 했는지 알 수 있음.
		System.out.println("userRequset.getAccessToken: "+ userRequest.getAccessToken());
		System.out.println("userRequest.getAttributes: "+ super.loadUser(userRequest).getAttributes());
		
		OAuth2User oauth2User = super.loadUser(userRequest);
		String provider = userRequest.getClientRegistration().getRegistrationId(); //google?		
		OAuth2UserInfo oAuth2UserInfo = null;
		if(provider.equals("google")) {
			System.out.println("구글 로그인 요청");
			oAuth2UserInfo = new GoogleUserInfo(oauth2User.getAttributes());		
		}else if(provider.equals("facebook")) {
			System.out.println("페이스북 로그인 요청");
			oAuth2UserInfo = new FacebookUserInfo(oauth2User.getAttributes());
		}else {
			System.out.println("현재 구글과 페이스북만 지원됩니다.");
		}
		String providerId = oAuth2UserInfo.getProviderId();
		String username = provider+"_"+oAuth2UserInfo.getProviderId();
		String password = new BCryptPasswordEncoder().encode("1234");
		String email = oauth2User.getAttribute("email");
		String role = "ROLE_USER";
		
		//해당 username이 이미 있는지 확인
		User userEntity = userRepository.findByUsername(username);
		
		//구글로 처음 로그인 하면 자동으로 회원가입 시킴.
		if(userEntity == null) {
			System.out.println("최초 구글 로그인으로 회원가입을 진행했습니다.");
			userEntity = User.builder()
					.username(username)
					.password(password)
					.email(email)
					.role(role)
					.provider(provider)
					.providerId(providerId)
					.build();
			userRepository.save(userEntity);
		}else {
			System.out.println("회원가입 이력이 있습니다. 자동 로그인을 진행했습니다.");
		}
		
		return new PrincipalDetails(userEntity, oauth2User.getAttributes()); //이 PrincipalDetails가 Authentication 객체 안에 들어가게 됨.
	}
}

이렇게 하면 제대로 작동하는 것을 확인할 수 있다.

 

 

저작자표시 (새창열림)

'취업 준비 > Spring security' 카테고리의 다른 글

10. TCP는 무엇인가?  (0) 2022.02.24
9. 네이버 OAuth 로그인  (0) 2022.02.24
7. PrincipalDetails 객체를 이용하여 2가지 로그인 방식 통합  (0) 2022.02.17
6. OAuth2 구글 로그인  (0) 2022.02.17
5. 시큐리티 권한처리  (0) 2022.02.16
'취업 준비/Spring security' 카테고리의 다른 글
  • 10. TCP는 무엇인가?
  • 9. 네이버 OAuth 로그인
  • 7. PrincipalDetails 객체를 이용하여 2가지 로그인 방식 통합
  • 6. OAuth2 구글 로그인
Purewater
Purewater
Purewater
프로그램 공부 일기장
Purewater
전체
오늘
어제
  • 분류 전체보기 (237)
    • Front-end (8)
      • Vue (8)
    • 포트폴리오 (3)
      • JSP SHOP (1)
      • Travelanner (1)
      • OAuth2 Blog (1)
    • 취업 준비 (70)
      • Spring boot (43)
      • JPA (1)
      • Spring security (14)
      • React (11)
      • 면접 기록 (1)
    • 국기훈련과정 (57)
      • JAVA 복습노트 (12)
      • Oracle SQL (9)
      • Web (15)
      • JSP (6)
      • Spring (10)
      • 프로젝트 (4)
      • Python (1)
    • 알고리즘 문제풀이 (17)
      • Python3 (13)
      • Kotlin (4)
    • 이것저것 지식 (9)
    • 클라우드 서버 (7)
      • Linux (7)
    • Backend (20)
      • node.js (9)
      • JAVA (6)
      • spring boot (5)
    • DB (1)
      • SQL (1)
    • 잡담 (1)
    • 강의 수강 (1)
    • CS 지식 (41)
      • 디자인패턴 (6)
      • 네트워크 (22)
      • 데이터베이스 (4)

블로그 메뉴

  • 대문
  • 태그
  • 방명록
  • 글쓰기

공지사항

인기 글

태그

  • PostgreSQL
  • spring
  • GUI
  • redis
  • 노드
  • db
  • SQL
  • Java
  • Oracle
  • JPA
  • node.js
  • Kotlin
  • 자바스크립트
  • node
  • Postman
  • js
  • git
  • gitignore
  • 오라클
  • 디자인패턴

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
Purewater
8. 페이스북 Oauth 로그인
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.