Google OAuth Setup

About

Spring Security둜 OAuth κ΅¬ν˜„ν•  λ•Œ μ£Όμ†Œ λ“±λ‘ν•˜λŠ” 게 λ„ˆλ¬΄ 많고 ν—·κ°ˆλ €μ„œ 레퍼런슀λ₯Ό 계속 보게 λ©λ‹ˆλ‹€. 고톡을 많이 λ°›μ•„ 이 참에 μ •λ¦¬ν•΄λ‘‘λ‹ˆλ‹€.

Keywords

  • OAuth Client ID, Client Secret - ν•΄λ‹Ή ID와 secret으둜 μ–΄λ–€ ꡬ글 OAuth 앱인지 μ‹λ³„ν•˜κ³  λ‘œκ·ΈμΈν•  κΆŒν•œμ„ μ–»μŠ΅λ‹ˆλ‹€. ꡬ글 (GCP)μ—μ„œ OAuth 앱을 λ§Œλ“€κ³  λ°œκΈ‰λ°›μ„ 수 μžˆμŠ΅λ‹ˆλ‹€.

    • λ°±μ—”λ“œκ°€ Redirect 포함 둜그인 처리λ₯Ό λͺ¨λ‘ ν•˜λŠ” μ›Ή 버전 둜그인의 경우 λ°±μ—”λ“œμ— λ“±λ‘ν•΄μ€˜μ•Ό ν•©λ‹ˆλ‹€. μ—¬κΈ°μ„œλŠ” 이 방식을 κΈ°μ€€μœΌλ‘œ κ°€μ΄λ“œλ₯Ό μž‘μ„±ν•©λ‹ˆλ‹€.

    • μžλ°”μŠ€ν¬λ¦½νŠΈ 방식 둜그인의 κ²½μš°μ—” ν”„λ‘ νŠΈμ—”λ“œμ— 등둝해야 ν•©λ‹ˆλ‹€.

  • λ°±μ—”λ“œ OAuth 둜그인 URL - e.g., http://localhost:8080/oauth2/authorize/google?redirect_uri=http://localhost:3000/auth/redirect

    • ν”„λ‘ νŠΈμ—”λ“œμ—μ„œ 맨 처음 λ°±μ—”λ“œλ‘œ μš”μ²­ν•˜λŠ” ꡬ글 둜그인 λ²„νŠΌμ— λ„£μ–΄μ£ΌλŠ” μ£Όμ†Œμž…λ‹ˆλ‹€.

    • Google 둜그인 λ°©μ‹μœΌλ‘œ 둜그인 ν•œ λ’€ ν”„λ‘ νŠΈμ—”λ“œμ˜ /auth/redirect둜 λŒμ•„μ™€λ‹¬λΌλŠ” μš”μ²­μž…λ‹ˆλ‹€.

  • λ°±μ—”λ“œ Redirect URI - e.g., http://localhost:8080/login/oauth2/code/google

    • ꡬ글 μ•±μ—μ„œ Authorized Redirect URI둜 λ“±λ‘ν•΄μ€˜μ•Ό ν•©λ‹ˆλ‹€. κ΅¬κΈ€μ—μ„œ 토큰을 λ°œκΈ‰ν•˜κ³  ν•΄λ‹Ή μ£Όμ†Œλ‘œ κ°€κ²Œ λ˜λŠ” λΆ€λΆ„μž…λ‹ˆλ‹€.

    • ν”„λ‘ νŠΈμ—”λ“œλŠ” μ•Œ ν•„μš” μ—†μŠ΅λ‹ˆλ‹€.

  • ν”„λ‘ νŠΈμ—”λ“œ Redirect URI - e.g., http://localhost:3000/auth/redirect

    • λͺ¨λ“  둜그인 μž‘μ—…μ„ 마치면 λ°±μ—”λ“œμ—μ„œ ν”„λ‘ νŠΈμ—”λ“œμ˜ ν•΄λ‹Ή μ£Όμ†Œλ‘œ redirect μ‹œν‚΅λ‹ˆλ‹€.

    • λ°±μ—”λ“œμ—μ„œ λ“±λ‘ν•΄μ€˜μ•Ό ν•©λ‹ˆλ‹€.

    • ν”„λ‘ νŠΈμ—”λ“œμ—μ„œ ν•΄λ‹Ή νŽ˜μ΄μ§€λ₯Ό λ§Œλ“€κ³ , λ°±μ—”λ“œμ—μ„œ μΏΌλ¦¬μŠ€νŠΈλ§μ— λ„£μ–΄μ€€ 토큰을 μ²˜λ¦¬ν•˜λŠ” 둜직(μΏ ν‚€ μ €μž₯ λ“±)을 κ΅¬ν˜„ν•΄μ•Ό ν•©λ‹ˆλ‹€. μ—¬κΈ°μ„œ λ‚˜μ˜¨ 토큰을 Authorization 헀더에 λ„£κ³  인증된 μš”μ²­μ„ 보낼 수 μžˆμŠ΅λ‹ˆλ‹€.

    • ꡬ글 μ•±μ—μ„œλŠ” μ•Œ ν•„μš” μ—†μŠ΅λ‹ˆλ‹€.

Details

일단 client-id와 client-secret을 λ‘˜ λ‹€ λ“±λ‘ν•΄μ€˜μ•Ό ν•©λ‹ˆλ‹€. JavaScript λ²„μ „μ˜ 둜그인이 μ•„λ‹Œ μ›Ή λ²„μ „μ˜ λ‘œκ·ΈμΈμ΄λ―€λ‘œ λ°±μ—”λ“œ μͺ½μ— λ„£μŠ΅λ‹ˆλ‹€. (application-oauth.yml)

  1. Google OAuth Appμ—μ„œ Authorized Redirect URI μΆ”κ°€

    `${BACKEND_URL}/login/oauth2/code/${providerType}`
    • 예λ₯Ό λ“€λ©΄ http://localhost:8080/login/oauth2/code/google μž…λ‹ˆλ‹€.

    • 이 μ£Όμ†Œλ₯Ό Google의 Authorized Redirect URI에 λ„£μ–΄μ€˜μ•Ό ν•©λ‹ˆλ‹€. 넣지 μ•ŠμœΌλ©΄ κ΅¬κΈ€μ—μ„œ unauthorized_redirect_uri μ—λŸ¬κ°€ λ°œμƒν•©λ‹ˆλ‹€.

  2. λ°±μ—”λ“œμ—μ„œ ν”„λ‘ νŠΈμ—”λ“œλ‘œ λŒμ•„κ°€λŠ” authorized redirect URI μΆ”κ°€

    app:
      oauth2:
          authorized-redirect-uris:
            - <http://localhost:3000/auth/redirect>
  3. λ°±μ—”λ“œμ—μ„œ SecurityConfiguration κ΅¬ν˜„ μ‹œ authorization κ΄€λ ¨ URI μΆ”κ°€

    @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .cors().and()
                    .csrf().disable()
                    .httpBasic().disable()
                    .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                    .authorizeRequests(authz -> authz
                            .anyRequest().permitAll()
                            .expressionHandler(expressionHandler()))
                    .oauth2Login(oAuthz -> oAuthz
                            .authorizationEndpoint()
                            .baseUri("/oauth2/authorize") // (4) ν”„λ‘ νŠΈμ—”λ“œλ‘œλΆ€ν„° OAuth 둜그인 μš”μ²­μ„ 받을 URI
                            .authorizationRequestRepository(cookieAuthorizationRequestRepository).and()
                            .redirectionEndpoint().baseUri("/*/oauth2/code/*").and() // (1) ꡬ글 μ•± κ΄€λ ¨ Redirection URI
                            .userInfoEndpoint().userService(oAuth2UserService).and()
                            .successHandler(oAuth2AuthenticationSuccessHandler)
                            .failureHandler(oAuth2AuthenticationFailureHandler));
    
            http
                    .addFilterBefore(authenticationJwtTokenFilter, UsernamePasswordAuthenticationFilter.class);
        }
  4. ν”„λ‘ νŠΈμ—”λ“œμ—μ„œ λ°±μ—”λ“œλ‘œ μš”μ²­ν•˜λŠ” λ²„νŠΌ κ΅¬ν˜„

    const providerType = 'google'
    const url = `${BACKEND_URL}/oauth2/authorize/${providerType}?redirect_uri=${FRONTEND_URL}/auth/redirect`
    • μ΄λ•Œ url을 λ‹¨μˆœ <a> νƒœκ·Έλ₯Ό 넣은 λ²„νŠΌμ— href 속성에 url을 λ„£μ–΄μ£ΌκΈ°λ§Œ ν•˜λ©΄ λ©λ‹ˆλ‹€.

  5. ν”„λ‘ νŠΈμ—”λ“œμ—μ„œμ˜ redirect URI에 λŒ€ν•œ 처리

    • λ‘œκ·ΈμΈμ„ μ™„λ£Œν•˜κ³  λ°±μ—”λ“œμ—μ„œ JWT 토큰 값을 ν”„λ‘ νŠΈμ—”λ“œμ˜ Redirect URL둜 μΏΌλ¦¬μŠ€νŠΈλ§μ„ 톡해 λ³΄λ‚΄μ€λ‹ˆλ‹€. (?access_token=XX&refresh_token=XXX)

    • /auth/redirect νŽ˜μ΄μ§€λ₯Ό λ§Œλ“€κ³ , ν•΄λ‹Ή νŽ˜μ΄μ§€μ— μ „λ‹¬λœ 쿼리λ₯Ό μ½μŠ΅λ‹ˆλ‹€. 쿼리λ₯Ό 읽어 토큰을 κ°€μ Έμ˜€κ³  쿠킀에 μ €μž₯ν•΄μ€˜μ„œ μ•±μ—μ„œ 관리해주면 λ©λ‹ˆλ‹€.

    • 이게 ν”„λ‘ νŠΈμ—”λ“œμ˜ authorized-redirect-uriμž…λ‹ˆλ‹€. λ°±μ—”λ“œμ—μ„œλ„ application-oauth.ymlμ—μ„œ λ“±λ‘ν•΄μ€λ‹ˆλ‹€.

Reference

λ ˆνΌλŸ°μŠ€λŠ” λ‹€μŒ κΈ€ ν•˜λ‚˜λ‘œ λ‹€ 해결이 λ©λ‹ˆλ‹€.

[Spring Boot] OAuth2 μ†Œμ…œ 둜그인 κ°€μ΄λ“œ (ꡬ글, 페이슀뢁, 넀이버, 카카였)

Last updated