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