OpenID Connect 및 NGINX Plus를 사용하여 앱 인증하기

이 포스트에서는 인증을 위해 Implicit Flow을 지원하는 OpenID Connect 공급자와 함께 NGINX Plus를 사용하는 방법을 설명합니다.

NGINX Plus R15 이상에서는 OpenID Connect 인증 코드 흐름에서 신뢰 당사자로 NGINX Plus를 사용할 수도 있습니다.

OAuth 2.0은 웹사이트 및 애플리케이션 인증의 유연성과 사용자 경험을 개선하는 데 많은 기여를 했습니다. 하지만 이름과는 달리 OAuth 2.0 사양은 최종 사용자 신원 확인에 대해서는 거의 언급하지 않고 Single Sign-On(SSO)에 대해서는 전혀 언급하지 않습니다. 바로 이 점이 OpenID Connect 가 필요한 이유입니다. 이 솔루션은 기본적으로 OAuth 2.0 액세스 토큰에 신원 정보를 전달하는 누락된 부분입니다.

OpenID Connect ID 토큰은 JSON Web Token(JWT) 사양을 준수합니다. JWT 토큰은 작고 전달하기 쉬우며 ID 정보를 설명하기 위한 공통의 핵심 스키마를 제공합니다. JWT의 가장 큰 장점은 API 클라이언트 인증부터 엔터프라이즈 애플리케이션에 대한 SSO 제공에 이르기까지 거의 모든 ID 사용 사례에 적용할 수 있다는 것입니다. 실제로 Google Apps를 사용하는 많은 조직은 Google을 ID 공급업체로 활용하여 엔터프라이즈 애플리케이션에 SSO를 제공할 수 있습니다. 즉, OpenID Connect 및 JWT를 사용한다고 해서 기존 웹 애플리케이션을 인증하거나 SSO를 제공하는 데 사용할 수 없는 것은 아닙니다.

NGINX Plus R10 이상에는 기본 JWT 지원이 포함되어 있어, 애플리케이션이 쉽게 사용할 수 있는 방식으로 토큰의 유효성을 검사하고 인증된 사용자의 ID로 Upstream 요청을 장식할 수 있습니다. 이 포스트에서는 애플리케이션 자체에 대한 변경 없이 기존 애플리케이션에 대해 SSO를 활성화하기 위해 NGINX Plus의 기본 JWT 지원을 사용하는 방법을 보여드립니다. 여기서는 Google을 ID 공급자로 사용하고 애플리케이션을 나타내는 간단한 웹사이트를 사용합니다. End-to-End 흐름은 다음과 같습니다.

Diagram depicting the processing flow for single sign-on (SSO) of clients with Google accounts; NGINX Plus validates user identity using OAuth 2.0 and OpenID Connect tokens, which comply with the JSON Web Token (JWT) standard

NGINX Plus는 OAuth 2.0 및 Google 기반 SSO용 OpenID Connect 를 사용하여 사용자 ID를 확인합니다.

목록

1. 웹 애플리케이션에 OpenID Connect 활성화하기
1-1. NGINX Plus 구성
1-2. HTML 기반 로그인 페이지
2. 부록 – Google OAuth 2.0 클라이언트 ID 만들기

1. 웹 애플리케이션에 OpenID Connect 활성화하기

이 예제에는 두 가지 구성 요소, 즉 NGINX Plus 구성과 HTML 로그인 페이지가 있습니다.

1-1. OpenID Connect NGINX Plus 구성

JWT 유효성 검사를 위한 NGINX Plus 구성은 매우 간단합니다.

server {
    listen 80;
    root /var/www/public_html;

    location /private/ {
        auth_jwt "Google account" token=$cookie_auth_token;
        auth_jwt_key_file /etc/nginx/google_certs.jwk;
    }
}

location 블록은 /private/으로 시작하는 URL에 대한 모든 요청을 인증해야 한다고 지정합니다. auth_jwt 지시문은 인증에 실패할 경우 401과 함께 반환되는 인증 영역과 요청에서 NGINX Plus가 JWT를 찾을 수 있는 영역을 정의합니다. 이 경우 auth_token이라는 쿠키에서 토큰을 찾을 것으로 예상합니다. 기본적으로 NGINX Plus는 클라이언트가 AJAX 애플리케이션 및 API 클라이언트에서 일반적으로 사용되는 Authorization 헤더를 사용하여 Bearer Token으로 JWT를 제공할 것으로 예상하지만, 이 예제에서처럼 다른 HTTP 헤더, 쿼리 문자열 인수 또는 쿠키에서 JWT를 가져올 수도 있습니다.

auth_jwt_key_file 지시문은 NGINX에 JWT의 서명 요소의 유효성을 검사하는 방법을 알려줍니다. 서명 유효성 검사는 JWT가 Google에서 발급되었으며 이후 수정되지 않았는지 확인합니다. Google은 공개 키를 게시하고 정기적으로 갱신합니다. 최신 키 집합을 유지하려면 이 샘플 crontab 항목에서와 같이 cron(8)을 사용하여 매시간마다 키를 가져옵니다.

0 * * * * wget https://www.googleapis.com/oauth2/v3/certs -O /etc/nginx/google_certs.jwk

1-2. HTML 기반 로그인 페이지

이 예제를 간단하게 만들기 위해 전체 애플리케이션을 구축하지 않습니다. 대신 다음과 같은 기본 HTML을 사용하여 로그인 페이지를 만들겠습니다. HTML 파일 이름은 /var/www/public_html/index.html입니다(NGINX Plus 구성에서 정의한 root 경로와 일치합니다).

<html>
<head>
    <meta http-equiv="cache-control" content="no-cache" />
    <meta http-equiv="expires" content="0" />
    <title>NGINX OpenID Connect demo</title>
    <script src="https://apis.google.com/js/platform.js" async defer></script>
    <meta name="google-signin-scope" content="profile email">
    <meta name="google-signin-client_id" 
          content="client-ID.apps.googleusercontent.com">
    <script src="/js.cookie.js"></script>
</head>
<body>
    <h2>NGINX OpenID Connect demo</h2>
    <hr/>
    <h3>Login with a Google account then visit the <a href="/private/">private area</a>.</h3>
    <table><tr><td>
    <div class="g-signin2" data-onsuccess="onSignIn" data-theme="dark"></div></td>
    <script>
      function onSignIn(googleUser) {
        var profile = googleUser.getBasicProfile();
        Cookies.set('auth_token', googleUser.getAuthResponse().id_token);
        document.getElementById('google_signout').innerHTML = '<a href="#" onclick="signOut();"><img src="' + profile.getImageUrl() + '" width=32 height=32>Sign out</a>';
      };
      function signOut() {
        var auth2 = gapi.auth2.getAuthInstance();
        auth2.signOut().then(function () {
          Cookies.remove('auth_token');
          document.getElementById('google_signout').innerHTML = '';
        });
      }
    </script>
    <td><div id="google_signout"></div></td>
    </tr></table>
    <hr/>
</body>
</html>

<head> 블록에서 두 가지 주요 종속성을 강조 표시했습니다.

  • <meta name=”google‑signin‑client_id”> 태그Google의 OAuth 2.0 JavaScript API를 사용하여 OAuth 2.0 최종 사용자 동의 및 인증 프로세스를 수행하고 있습니다. 이를 통해 로그인 버튼이 제공되며 로그인 여부를 감지할 수 있습니다. Google에서 웹사이트를 인증하려면 OAuth 2.0 클라이언트 ID를 생성하고 이를 이 태그의 콘텐츠 속성으로 제공하여 클라이언트 ID Placeholder를 대체해야 합니다. 새 OAuth 2.0 클라이언트 ID를 만드는 방법에 대한 지침은 이 문서 하단의 부록을 참조하세요.
  • <script src=”/js.cookie.js”> 태그 – OAuth 2.0 액세스 토큰에서 ID 토큰을 추출하여 웹사이트에 전송할 쿠키를 생성할 수 있는 cookie-parser가 필요합니다. 이 태그에 포함된 JavaScript 쿠키 라이브러리를 사용하여 Cookies.set 줄이 이 작업을 수행합니다.

이제 Google의 로그인 메커니즘을 갖춘 공개 홈페이지와 NGINX Plus로 보호되는 비공개 영역이 생겼습니다. 비공개 영역에 대한 콘텐츠를 만들지 않았으므로 해당 영역에 액세스하려고 할 때 404 오류가 발생할 수 있다는 점에 유의하세요.

2. 부록 – Google OAuth 2.0 클라이언트 ID 만들기

Google은 이 지침을 발행할 당시 Google API GUI를 정확하게 표현하기 위해 최선을 다했지만, GUI는 매우 동적이며 메뉴 옵션과 위치가 변경될 수 있습니다. 이 지침을 참조로 삼아 필요에 따라 현재 GUI에 맞게 조정하세요.

1. Google API 대시보드(https://console.cloud.google.com/apis/dashboard?project=caramel-medley-368906)에 액세스합니다.

열리는 페이지는 Google API 사용 기록에 따라 달라집니다. 계정을 만들고, 이용 약관에 동의하고, 이 지침에 표시되지 않은 다른 단계를 수행해야 할 수도 있습니다.

다음 스크린샷은 대시보드의 왼쪽 상단 모서리를 보여줍니다. Google API 로고 오른쪽에 있는 단어를 클릭합니다(이전에 프로젝트를 만든 적이 있는 경우에는 프로젝트라는 단어 대신 해당 이름이 표시될 수 있음). Create project를 선택합니다.

When creating a Google OAuth 2.0 client ID, select 'Create project' from the drop-down menu next to the Google APIs logo in the upper left corner of the API Manager dashboard.

2. 새 프로젝트를 생성합니다. 여기서는 새 프로젝트를 NGINX OpenID라고 합니다. Create 버튼을 클릭한 후 프로젝트가 생성되었다는 알림이 표시되기까지 몇 초 정도 걸릴 수 있습니다.

When creating a Google OAuth 2.0 client ID, specify a name for your new project.

3. 프로젝트에 Google+ API를 사용하도록 설정합니다. OAuth 2.0 인증 및 ID 서비스를 제공합니다.

(API Manager Dashboard가 창의 메인 부분에 아직 표시되지 않으면 화면 왼쪽의 탐색 영역에서 Dashboard를 클릭합니다.)

Google+ API를 활성화하는 첫 번째 단계는 ENABLE API 버튼을 클릭하는 것입니다.

When creating a Google OAuth 2.0 client ID, while on the API Manager Dashboard screen click the ENABLE API button.

4. Social APIs 섹션에서 Google+ API를 클릭합니다.

When creating a Google OAuth 2.0 client ID, select the Google+ API from the list of 'Social APIs' on the Library screen of the API Manager.

5. ENABLE 버튼을 클릭합니다.

When creating a Google OAuth 2.0 client ID, after having selected the Google+ API, click the 'Enable' button.

6. 프로젝트에 대한 자격 증명을 만들려면 화면 왼쪽의 탐색 영역에서 Credentials을 클릭한 다음 Create credentials 버튼을 클릭합니다.

드롭다운 메뉴에서 OAuth client ID를 선택합니다.

When creating a Google OAuth 2.0 client ID, select 'OAuth client ID' as the type of credential to create.

7. Web application 라디오 버튼을 선택합니다. Authorized JavaScript origins 필드에 NGINX Plus가 설치된 호스트의 URL과 웹 애플리케이션에 OpenID 연결 사용 설정에서 listen 지시문의 매개변수로 지정한 포트 번호를 지정합니다(예: mydomain.example.com:80). 이 예에서는 localhost를 사용하지만 실제 NGINX Plus 인스턴스의 호스트 이름과 포트를 입력해야 합니다.

Create 버튼을 입력합니다.

When creating a Google OAuth 2.0 client ID, specify the 'Web application' application type and specify the URL for your NGINX Plus host as an 'Authorized JavaScript origin'.;

8. OAuth client 창이 나타나면 클라이언트 ID와 클라이언트 비밀번호를 보고합니다. 클라이언트 ID를 애플리케이션의 <meta name=”google-signin-client_id”> 태그의 콘텐츠 속성에 복사합니다(위에 표시된 강조 표시된 client-ID 자리 표시자를 대체). 클라이언트 Secret는 필요하지 않습니다.

When you have successfully created a Google OAuth 2.0 client ID, it appears in the 'OAuth client' window along with the client secret.

9. 기본 Credentials 화면에서 OAuth consent screen을 클릭합니다. 이메일 주소와 제품 이름을 입력합니다(다른 모든 필드는 선택 사항입니다).

When creating a Google OAuth 2.0 client ID, specify your email address and the product name on the 'OAuth consent screen' under API Manager > Credentials.

자격 증명을 사용하는 샘플 애플리케이션 만들기에 대한 섹션으로 돌아갑니다.

NGINX Plus의 기본 JWT 지원을 직접 사용해 보거나 테스트해 보려면 지금 30일 무료 평가판을 신청하거나 사용 사례에 대해 최신 소식을 빠르게 전달받고 싶으시면 아래 뉴스레터를 구독하세요.