Azure Static Web Apps: login_hint 이제 작동합니다

발행: (2025년 12월 24일 오전 02:37 GMT+9)
3 min read
원문: Dev.to

Source: Dev.to

이 게시물은 Azure Static Web Apps (SWA)에서 기본적으로 작동하지 않는 login_hint 구현을 보여줍니다.

References

(no items listed)

Auth Flow

  1. 이동

    https://swa.azurestaticapps.net/.auth/login/aad?login_hint=user@mail.com
  2. 사용자는 다음으로 리디렉션됩니다

    https://swa.azurestaticapps.net/.auth/login/aad?post_login_redirect_uri=/.auth/complete&staticWebAppsAuthNonce=aTakZLY%2fCmXnnD%2foxHxXW%2fWDcXGAy27B84se3dzrpE7UcwEFqKGy2VNnXRqvPInletF6R26ZDfdMSD0kKda41Y8%2b3BXO%2bHUoG3VEbaJpSkhdQ%2fRFWgFb1nKNWZ80dtzW
  3. 그 다음

    https://login.microsoftonline.com/c74da02d-281d-4a45-a4af-cc520eafa6e3/oauth2/v2.0/authorize?
    response_type=code+id_token&
    redirect_uri=https%3A%2F%2Fswa.azurestaticapps.net%2F.auth%2Flogin%2Faad%2Fcallback&
    client_id=6c3476f8-54c2-4322-8401-f7774963a1e1&
    scope=openid+profile+email&
    response_mode=form_post&
    resource=https%3A%2F%2Fgraph.microsoft.com&
    nonce=9108b12ec87a4effa26bd5287d792605_20251223165427&
    state=redir%3D%252F.auth%252Fcomplete

Problem

login_hint가 사라지고 login.microsoftonline.com 엔드포인트에 전달되지 않습니다.

Fix

Azure Functions v4Node를 사용하고 HTTP/2 요청으로 미들웨어를 구현했습니다.

Why HTTP/2?

인증 흐름은 HTTP/2 프로토콜에 속하는 의사 헤더(:authority, :path)를 사용합니다.

전체 프로젝트 설정은 나중에 제공하겠습니다.

Steps

  1. User request – 사용자는 다음으로 이동합니다

    https://swa.azurestaticapps.net/api/whoami?login_hint=user@mail.com
  2. Function trigger – 요청은 app.http("whoami"... ) 함수에 의해 수신되고 handler 함수가 호출됩니다.

  3. Processing – 핸들러는 요청에서 원본 SWA URL과 login_hint를 추출하고, 리디렉션을 따라가며 쿠키를 등록하고, 최종적으로 적절한 nonce 쿠키를 포함한 login.microsoftonline.com 엔드포인트용 전체 URL을 구성합니다.

  4. Redirect – 함수는 SWA 페이지에 리디렉션 응답을 반환하고, 이후 인증 흐름을 완료합니다.

  5. Error handling – 문제가 발생하면 함수는 /.auth/login/aad 로 다시 리디렉션하고, context.log 로 상세 정보를 기록하며, 로그는 Azure 포털에서 확인할 수 있습니다.

Function Code

import { app } from "@azure/functions";
import { connect } from "node:http2";

let count = 5;

/**
 * Recursively follows redirects using HTTP/2 and injects login_hint when needed.
 *
 * @param {string} url               – The URL to request.
 * @param {PromiseWithResolvers} pWithResolvers  – Optional promise resolvers (for recursion).
 * @param {Object} headersObj        – HTTP/2 pseudo‑headers for the request.
 * @param {string} loginHint         – The login_hint value (may be empty).
 * @returns {Promise}
 */
async function getData(url, pWithResolvers, headersObj = {}, loginHint) {
    const p = pWithResolvers ?? Promise.withResolvers();
    const clientSession = connect(url);

    clientSession.on("error", (err) => console.error(err));

    const req = clientSession.request({
        ...headersObj,
    });

    req.on("response", (headers) => {
        req.on("error", (e) => {
            context.log(`problem with request:`, {
                msg: e.message,
                stack: e.stack,
                e,
            });
            clientSession.close();
            p.reject(e.message);
        });

        const status = headers
Back to Blog

관련 글

더 보기 »

JSON Web Token (JWT) 이해하기

어떤 시점에 웹 애플리케이션을 만들 때, 시스템을 위한 인증 솔루션을 개발해야 합니다. 이를 위한 다양한 전략이 있으며, 예를 들어…