์™ธ๋ถ€ ID๋กœ ์„ธ์…˜ ๊ด€๋ฆฌ

์ด ๋ฌธ์„œ์—์„œ๋Š” ์ธ์ฆ์— ์™ธ๋ถ€ ID๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ IAP(Identity-Aware Proxy)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ธ์…˜์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์„ธ์…˜ ์ƒˆ๋กœ๊ณ ์นจ

Identity Platform ์„ธ์…˜์€ 1์‹œ๊ฐ„ ๋™์•ˆ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค. ์„ธ์…˜์ด ๋งŒ๋ฃŒ๋˜๋ฉด ์•ฑ์ด ์ธ์ฆ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋””๋ ‰์…˜๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ธ์ฆ ํŽ˜์ด์ง€์—๋Š” Identity Platform ์ƒˆ๋กœ๊ณ ์นจ ํ† ํฐ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž์˜ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๊ฐ€ ์—ฌ์ „ํžˆ ์œ ํšจํ•˜๋ฉด UI๋ฅผ ํ‘œ์‹œํ•˜์ง€ ์•Š๊ณ  ์žฌ์ธ์ฆ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ์ตœ๊ทผ์— ์ด๋ฉ”์ผ ๋˜๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋ณ€๊ฒฝํ–ˆ๊ฑฐ๋‚˜ ํ† ํฐ์„ ์ทจ์†Œํ•œ ๋‹ค๋ฅธ ์กฐ์น˜๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ ์ธ์ฆ ํ๋ฆ„์„ ๋‹ค์‹œ ์™„๋ฃŒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋น„AJAX ์š”์ฒญ ์ฒ˜๋ฆฌ

๋น„AJAX ์š”์ฒญ์€ ์ธ์ฆ ํŽ˜์ด์ง€๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ตฌ์„ฑ๋˜์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฆฌ๋””๋ ‰์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

AJAX ์š”์ฒญ ์ฒ˜๋ฆฌ

Chrome ๋ฐ ๋‹ค๋ฅธ ๋ธŒ๋ผ์šฐ์ €๋Š” ์„œ๋“œ ํŒŒํ‹ฐ ์ฟ ํ‚ค๋ฅผ ๋‹จ๊ณ„์ ์œผ๋กœ ์ค„์—ฌ๊ฐ€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์„œ๋“œ ํŒŒํ‹ฐ ์ฟ ํ‚ค๊ฐ€ ์‚ฌ์šฉ ์ค‘์ง€๋˜์–ด ์žˆ์œผ๋ฉด ์ด ํŽ˜์ด์ง€์—์„œ AJAX ์š”์ฒญ์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ๊ถŒ์žฅ์‚ฌํ•ญ์ด ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ AJAX ์š”์ฒญ์˜ ์†Œ์Šค์™€ ๋Œ€์ƒ์„ ๋ชจ๋‘ ๋™์ผํ•œ ์‚ฌ์ดํŠธ์—์„œ ๊ฐ€์ ธ์˜จ ๊ฒฝ์šฐ ์ œ๊ณต๋œ ์ถ”์ฒœ ํ•ญ๋ชฉ์€ ๊ณ„์† ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

Chrome์—์„œ ์„œ๋“œ ํŒŒํ‹ฐ ์ฟ ํ‚ค ๊ด€๋ฆฌ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ Chrome์—์„œ ์ฟ ํ‚ค ์‚ญ์ œ, ํ—ˆ์šฉ, ๊ด€๋ฆฌ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

๋งŒ๋ฃŒ๋œ ํ† ํฐ์œผ๋กœ AJAX ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด ์š”์ฒญ์€ 401: Unauthorized ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ ์†”๋ฃจ์…˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ๊ตฌํ˜„ํ•˜์„ธ์š”.

  • HTTP 401 ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ์„ธ์…˜ ์ƒˆ๋กœ๊ณ ์นจ์„ ๊ฐ€๋ฆฌํ‚ค๋„๋ก iframe์„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
  • ์‚ฌ์šฉ์ž๊ฐ€ ์„ธ์…˜ ์ƒˆ๋กœ๊ณ ์นจ์„ ๊ฐœ๋ณ„ ํƒญ์œผ๋กœ ์ˆ˜๋™ ๋กœ๋“œํ•˜๋„๋ก ์ง€์‹œํ•ฉ๋‹ˆ๋‹ค.

AJAX ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ 401 ๋Œ€์‹  302 ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ์ˆ˜์‹ ํ•˜๋Š” ๊ฒฝ์šฐ ๊ฐ’์ด XMLHttpRequest์ธ X-Requested-With ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์š”์ฒญ์ด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ์‹œ์ž‘๋œ๋‹ค๋Š” ๊ฒƒ์„ IAP์— ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

ํ”„๋กœ๊ทธ๋ž˜๋งคํ‹ฑ ๋ฐฉ์‹์œผ๋กœ HTTP 401 ์ฒ˜๋ฆฌ

ํ”„๋กœ๊ทธ๋ž˜๋งคํ‹ฑ ๋ฐฉ์‹์œผ๋กœ HTTP 401 ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด AJAX ์„ธ์…˜์„ ์ƒˆ๋กœ ๊ณ ์น˜๋Š” ๋ฐ ๊ถŒ์žฅ๋˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. ์˜ค๋ฅ˜๋ฅผ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

    if (response.status === 401) {
      statusElm.innerHTML = 'Login stale. <input type="button" value="Refresh" onclick="sessionRefreshClicked();"/>';
    }

  2. ์ฐฝ์„ ์—ด์–ด์„œ ์‚ฌ์šฉ์ž๋ฅผ ์žฌ์ธ์ฆํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ถ”๊ฐ€ํ•œ ๋‹ค์Œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ๋‹ซ์Šต๋‹ˆ๋‹ค.

    var iapSessionRefreshWindow = null;
    
    function sessionRefreshClicked() {
      if (iapSessionRefreshWindow == null) {
        iapSessionRefreshWindow = window.open("/?gcp-iap-mode=DO_SESSION_REFRESH");
        window.setTimeout(checkSessionRefresh, 500);
      }
      return false;
    }
    
    function checkSessionRefresh() {
      if (iapSessionRefreshWindow != null && !iapSessionRefreshWindow.closed) {
        // Attempting to start a new session.
        // XMLHttpRequests is used by the server to identify AJAX requests
        fetch('/favicon.ico', {
              method: "GET",
              credentials: 'include',
              headers: {
                  'X-Requested-With': 'XMLHttpRequest'
              }
        .then((response) => {
          // Checking if browser has a session for the requested app
          if (response.status === 401) {
            // No new session detected. Try to get a session again
            window.setTimeout(checkSessionRefresh, 500);
          } else {
            // Session retrieved.
            iapSessionRefreshWindow.close();
            iapSessionRefreshWindow = null;
          }
        })
        });
      } else {
        iapSessionRefreshWindow = null;
      }
    }

iframe ์‚ฌ์šฉ

ํ”„๋กœ๊ทธ๋ž˜๋งคํ‹ฑ ๋ฐฉ์‹์œผ๋กœ HTTP 401์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ ๋‹ค์Œ์œผ๋กœ ์ข‹์€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ์„ธ์…˜ ์ƒˆ๋กœ๊ณ ์นจ์„ ๊ฐ€๋ฆฌํ‚ค๋Š” iframe์„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

iframe์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด IAP ๋ณด์•ˆ ์›น ์•ฑ๊ณผ ๋™์ผํ•œ ๋„๋ฉ”์ธ์— ์ปค์Šคํ…€ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋ฅผ ๊ตฌ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ์ง€ ์•Š์œผ๋ฉด ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ต์ฐจ ์ถœ์ฒ˜ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ ๊ตฌ์„ฑ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ปค์Šคํ…€ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ ๋งŒ๋“ค๊ธฐ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

iframe ์‚ฌ์šฉ ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

<iframe src="https://example.com/some/path?gcp-iap-mode=SESSION_REFRESHER" style="width:0;height:0;border:0; border:none;"></iframe>

์„ธ์…˜ ์ƒˆ๋กœ๊ณ ์นจ ๋กœ๋“œ

์ตœํ›„์˜ ์ˆ˜๋‹จ์œผ๋กœ ์‚ฌ์šฉ์ž์—๊ฒŒ ์„ธ์…˜ ์ƒˆ๋กœ๊ณ ์นจ์„ ์ˆ˜๋™์œผ๋กœ ๋กœ๋“œํ•˜๋„๋ก ์ง€์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ๋ณ„๋„์˜ ํƒญ์—์„œ ๋‹ค์Œ URL์„ ์—ด๋„๋ก ์ง€์‹œํ•˜๋Š” ์ง€์นจ์„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋˜๋Š” ์„ค๋ช…์„œ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

https://example.com/some/path?gcp-iap-mode=SESSION_REFRESHER

์‚ฌ์šฉ์ž ๋กœ๊ทธ์•„์›ƒ

IAP ๋ฆฌ์†Œ์Šค์—์„œ ์‚ฌ์šฉ์ž๋ฅผ ๋กœ๊ทธ์•„์›ƒ์‹œํ‚ค๋ ค๋ฉด ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜ ?gcp-iap-mode=GCIP_SIGNOUT์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด App Engine ์•ฑ์—์„œ URL์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

https://example.com/some/path?gcp-iap-mode=GCIP_SIGNOUT

์‚ฌ์šฉ์ž๋Š” ๋กœ๊ทธ์•„์›ƒํ•œ ํ›„ ๋‹ค์‹œ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋””๋ ‰์…˜๋ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  ๋ฆฌ์†Œ์Šค์™€ ์„ธ์…˜์—์„œ ์‚ฌ์šฉ์ž๋ฅผ ๋กœ๊ทธ์•„์›ƒ์‹œํ‚ค๋ ค๋ฉด API ํ‚ค์™€ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ถ”๊ฐ€๋œ mode=signout์„ ์‚ฌ์šฉํ•˜์—ฌ ์ธ์ฆ URL๋กœ ๋ฆฌ๋””๋ ‰์…˜ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

https://auth.example.com/?apiKey=API-KEY&mode=signout

๋กœ๊ทธ์•„์›ƒ์ด ์™„๋ฃŒ๋œ ํ›„์—๋„ ์‚ฌ์šฉ์ž๋Š” ํŽ˜์ด์ง€์— ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž์—๊ฒŒ ๋กœ๊ทธ์•„์›ƒํ–ˆ๋‹ค๋Š” ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณตํ•˜๋ ค๋ฉด AuthenticationHandler ๊ฐ์ฒด์—์„œ completeSignOut() ์ฝœ๋ฐฑ์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

ํ…Œ๋„ŒํŠธ ๊ฐ„ ์ „ํ™˜

๊ฒฝ์šฐ์— ๋”ฐ๋ผ ์‚ฌ์šฉ์ž๋Š” ๋™์ผํ•œ IAP ๋ฆฌ์†Œ์Šค์— ์—ฌ๋Ÿฌ ํ…Œ๋„ŒํŠธ๋กœ ์ธ์ฆํ•˜๋ ค๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์„œ๋กœ ๋‹ค๋ฅธ ์ˆ˜์ค€์˜ ์•ก์„ธ์Šค ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๋Š” ๋ฉ€ํ‹ฐ ํ…Œ๋„ŒํŠธ์— ์†ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋” ์ ๊ฑฐ๋‚˜ ๋” ํฐ ๊ถŒํ•œ์ด ์žˆ๋Š” ํ…Œ๋„ŒํŠธ๋กœ ๋ณ€๊ฒฝํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ…Œ๋„ŒํŠธ ์„ ํƒ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ฐ•์ œ๋กœ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜๋ ค๋ฉด ?gcp-iap-mode=CLEAR_LOGIN_COOKIE๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. ์˜ˆ๋ฅผ ๋“ค์–ด App Engine ์•ฑ์—์„œ URL์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

https://PROJECT-ID.appspot.com/some/path?gcp-iap-mode=CLEAR_LOGIN_COOKIE

๋‹ค์Œ ๋‹จ๊ณ„