일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- 웹 서버
- Container
- 가상화
- virtualization
- spring cloud
- 영속성 컨텍스트
- CS
- Spring Security
- spring boot
- 스프링 부트
- JPA
- spring batch
- 자바
- 스프링 배치
- 백엔드
- mysql
- 컨테이너
- CI/CD
- HTTP
- Spring
- ORM
- Java
- computer science
- 스프링 시큐리티
- web server
- 도커
- vm
- 배포
- 데이터베이스
- 스프링
- Today
- Total
개발 일기
[Chrome Extension] 크롬 익스텐션 구글 소셜 로그인 처리 본문
탄지 프로젝트를 진행하던 도중 기존에 웹에서 연결하던 것과 똑같이 처리했더니 제대로 처리가 되지 않았다.
기존 웹에서 구글 소셜 로그인을 한다고 가정해보자.
프론트엔드에서 "구글로 로그인하기" 버튼을 클릭하면, Spring Security와 OAuth2 Client를 사용해 https://drinkguide.store/oauth2/authorization/google로 요청을 보낸다. 이후, 설정된 redirect-uri로 리다이렉트되며 실제 Google OAuth2 로그인이 진행된다. 소셜 로그인에 성공하면, Spring 서버는 callback-uri로 리다이렉트하면서 쿼리 파라미터로 accessToken과 refreshToken을 포함하여 반환한다.
그러나 똑같이 크롬 익스텐션으로 구현을 했더니 제대로 동작하지 않았다.
그래서 원인을 분석해봤다.
문제 해결
백엔드
우선, 크롬 익스텐션의 경우 URL이 기존 웹과는 다른 형식인 것을 확인할 수 있었습니다. 이는 크롬 익스텐션에서 우클릭으로 DevTools 개발자 도구를 통해 확인할 수 있었다.
chrome-extension://{확장프로그램 ID} 과 같은 형태를 한 URL을 가지고 있었다.
그래서 callback-uri: chrome-extension://cpleniffdlfncjgdgdjdfepkjbjhfbnn/index.html라고 서버에서 설정해주고
구글 클라우드에서 OAuth2.0 Client ID를 생성할때 크롬 확장프로그램이 아닌 웹 어플리케이션으로 생성해줘야했다.
프론트
그리고 프론트도 직접 손봤는데
/* Login.js */
import React from "react";
const Login = () => {
// 구글 로그인 처리 함수
const handleGoogleLogin = () => {
chrome.windows.create(
{
url: "https://drinkguide.store/oauth2/authorization/google", // 실제 로그인 URL로 대체
type: "popup",
width: 500,
height: 700,
},
(newWindow) => {
const pollForUrlChange = setInterval(() => {
chrome.tabs.get(newWindow.tabs[0].id, (tab) => {
if (tab.url.includes("chrome-extension://")) {
clearInterval(pollForUrlChange);
chrome.windows.remove(newWindow.id); // 로그인 팝업 닫기
// 쿼리 파라미터에서 accessToken과 refreshToken 추출
const params = new URL(tab.url).searchParams;
const accessToken = params.get("accessToken");
const refreshToken = params.get("refreshToken");
if (accessToken && refreshToken) {
saveTokensToStorage(accessToken, refreshToken);
console.log("Tokens saved:", { accessToken, refreshToken });
// 토큰 저장 후 홈 화면으로 리디렉션 (React 내비게이션 사용 안함)
chrome.tabs.update(tab.id, { url: "chrome-extension://{YOUR_EXTENSION_ID}/index.html" });
} else {
console.error("Failed to retrieve tokens.");
}
}
});
}, 500); // 500ms마다 확인
}
);
};
// 토큰을 chrome.storage.local에 저장
const saveTokensToStorage = (accessToken, refreshToken) => {
chrome.storage.local.set({ accessToken, refreshToken }, () => {
console.log("Tokens saved to storage.");
});
};
return <button onClick={handleGoogleLogin}>Login with Google</button>;
};
export default Login;
먼저, 사용자가 "Login with Google" 버튼을 클릭하면 handleGoogleLogin 함수가 실행된다.
이 함수는 Chrome Extension의 팝업 윈도우를 생성하여 사용자를 OAuth 인증 URL로 이동시킨다.
여기서는 https://drinkguide.store/oauth2/authorization/google URL이 사용된다.
팝업 윈도우가 생성되면, 주기적으로 (500ms 간격으로) 탭의 URL을 확인하는 pollForUrlChange 함수가 실행된다. 이 함수는 팝업에서 진행 중인 Google OAuth 인증이 완료되어 리디렉션 URL(백엔드 기준 callback-uri)로 이동했는지를 감지한다. 리디렉션 URL은 확장 프로그램의 리소스 URL (예: chrome-extension://)로 구성되며, 이 URL에 백엔드 단에서 인증에 성공했기때문에 accessToken과 refreshToken을 발급받아 쿼리 파라미터로 포함되어 있다.
리디렉션 URL로 이동했음을 감지하면 pollForUrlChange 함수는 실행을 중단하고, 팝업 윈도우를 닫는다.
이후, URL에서 쿼리 파라미터를 추출하여 accessToken과 refreshToken 값을 얻는다.
토큰이 정상적으로 추출되면, saveTokensToStorage 함수를 통해 Chrome의 storage.local API를 사용해 로컬 저장소에 토큰을 저장한다. 저장 후에는 홈 화면으로 리디렉션하기 위해 chrome.tabs.update 메서드가 호출되어 확장 프로그램의 메인 화면 URL로 사용자를 이동시킨다.
'TroubleShooting' 카테고리의 다른 글
[Spring Boot] S3 PresignedURL으로 파일(이미지) 조회 시 AOP 적용 (0) | 2024.12.12 |
---|---|
[TroubleShooting] SpringBoot 멀티모듈 프로젝트 빌드 이슈(jar와 bootJar) (0) | 2024.11.22 |