테마
응답 헤더 / Body 시그널 활용
logi 는 RFC 6749 표준 응답에 더해 RP 서버가 콘솔에 들어오지 않고도 디버깅·모니터링에 쓸 수 있는 신호들을 동봉합니다. 이 문서는 그 신호들을 미들웨어 단에서 잡아 서버 로그· 관측 시스템에 자동으로 흘려보내는 패턴을 보여줍니다.
시그널 카탈로그
Body 필드 (4xx 응답)
| 필드 | 항상 존재 | 용도 |
|---|---|---|
error | ✅ | 기계 판독 코드 (RFC 6749 §5.2) |
error_description | ✅ | 1줄 설명 |
error_uri | ✅ | 이 코드의 docs 앵커 |
request_id | 응답마다 | 콘솔 request_logs 와 동일 키 |
응답 헤더 (모든 응답)
| 헤더 | 언제 | 용도 |
|---|---|---|
X-Logi-Request-Id | 4xx 시 항상 | body 가 비어있는 경우(HEAD, error rendering 실패)에도 trace |
X-Logi-Console-Url | 4xx + RP 인증 성공 시 | 콘솔 request_logs 의 해당 요청으로 직링크 |
X-Logi-Scope-Drift | 200 응답 + drift 진행 중일 때 | 등록 안 된 scope 감지 — 즉시 알림용 |
패턴 1: 모든 4xx 응답을 자동 로깅
Node.js / Express + axios
js
import axios from 'axios'
const logiClient = axios.create({ baseURL: 'https://api.1pass.dev' })
logiClient.interceptors.response.use(
(res) => res,
(err) => {
if (err.response?.status >= 400 && err.response?.status < 500) {
const { data, headers, status } = err.response
console.warn('[logi] 4xx', {
status,
error: data?.error,
error_description: data?.error_description,
error_uri: data?.error_uri,
request_id: data?.request_id || headers['x-logi-request-id'],
console_url: headers['x-logi-console-url'], // 운영자가 즉시 클릭
})
}
return Promise.reject(err)
}
)Rails + Faraday
ruby
class LogiResponseLogger < Faraday::Middleware
def on_complete(env)
return unless env.status >= 400 && env.status < 500
body = JSON.parse(env.body) rescue {}
Rails.logger.warn(
"[logi] 4xx",
status: env.status,
error: body["error"],
error_description: body["error_description"],
error_uri: body["error_uri"],
request_id: body["request_id"] || env.response_headers["x-logi-request-id"],
console_url: env.response_headers["x-logi-console-url"]
)
end
endPython + requests
python
import logging, requests
def log_logi_4xx(resp: requests.Response):
if not (400 <= resp.status_code < 500):
return
body = resp.json() if "json" in resp.headers.get("content-type", "") else {}
logging.warning(
"[logi] 4xx",
extra={
"status": resp.status_code,
"error": body.get("error"),
"error_description": body.get("error_description"),
"error_uri": body.get("error_uri"),
"request_id": body.get("request_id") or resp.headers.get("X-Logi-Request-Id"),
"console_url": resp.headers.get("X-Logi-Console-Url"),
},
)패턴 2: Sentry / DataDog 에 trace 자동 연결
request_id 를 RP 의 distributed tracing key 와 묶으면, RP 자기 dashboard 에서 "이 사용자의 결제 실패 → logi 토큰 발급 실패" 까지 한 트레이스로 따라갈 수 있습니다.
js
import * as Sentry from '@sentry/node'
logiClient.interceptors.response.use(undefined, (err) => {
if (err.response?.status >= 400) {
const reqId = err.response.data?.request_id ||
err.response.headers['x-logi-request-id']
Sentry.withScope((scope) => {
scope.setTag('logi.request_id', reqId)
scope.setTag('logi.error', err.response.data?.error)
scope.setExtra('logi.console_url', err.response.headers['x-logi-console-url'])
Sentry.captureException(err)
})
}
return Promise.reject(err)
})이렇게 하면 Sentry 이슈 페이지에서 logi 콘솔로 1-click 점프 가능.
패턴 3: Scope drift 알림 (200 응답)
토큰 응답이 정상이어도 RP 가 등록 안 된 scope 를 요청 중이면 X-Logi-Scope-Drift 헤더에 누락 scope 가 콤마로 들어옵니다 — 7일 이내 자동 알림 + 콘솔에서도 표시.
js
logiClient.interceptors.response.use((res) => {
const drift = res.headers['x-logi-scope-drift']
if (drift) {
console.warn('[logi] scope drift detected:', drift.split(','),
'— 콘솔에서 등록 scope 를 업데이트하세요.')
}
return res
})이 시그널은 token 응답마다 동봉되므로, RP 가 scope 변경을 잊고 배포해도 7일 안에 서버 로그에 자동으로 알람이 뜹니다.
패턴 4: 사용자에게 노출할 1줄 메시지
error_description 은 한국어/영어 혼용일 수 있고 기술적입니다. 사용자에게 보여줄 때는 error 코드 → 사용자 메시지 매핑 테이블을 RP 가 만들어두는 것을 권장:
ts
const USER_FACING: Record<string, string> = {
invalid_grant: '로그인이 만료됐어요. 다시 시도해주세요.',
access_denied: '로그인이 취소됐어요.',
rate_limited: '요청이 너무 많아요. 잠시 후 다시 시도해주세요.',
invalid_scope: '앱 설정 문제로 일시적으로 로그인할 수 없어요.',
}
function userFacingMessage(error: string) {
return USER_FACING[error] ?? '잠시 후 다시 시도해주세요.'
}기술 정보(error, request_id, console_url)는 서버 로그로, 사용자에겐 친절한 1줄만 — 이렇게 분리해야 사용자가 stack trace 같은 걸 보지 않습니다.
운영 체크리스트
- [ ] RP 서버가 4xx 시
error,error_description,request_id셋을 모두 INFO 레벨로 기록한다 - [ ]
X-Logi-Console-Url헤더를 alerting 메시지에 포함시킨다 (운영자 1-click 점프) - [ ]
X-Logi-Scope-Drift헤더가 뜨면 RP 의 monitoring 시스템에 medium-priority 알람을 발사한다 - [ ]
request_id를 RP 의 trace ID 와 동일 필드에 매핑하거나, 적어도 같은 line 에 출력한다 - [ ] 사용자 노출 메시지는
error코드 매핑 테이블을 거친 한국어로만 제한한다
보안 주의
응답 헤더와 body 의 추가 시그널은 모두 PII 가 아닙니다 — request_id, error code, console URL 만 포함됩니다. 사용자 식별자(email, sub), 토큰 값, secret 은 절대 포함되지 않으므로 일반 로그에 남겨도 안전합니다.
참고
- OAuth 오류 코드 — 모든
error_uri가 가리키는 곳 - Scope drift 정책 — 헤더 발사 조건
- Recommended architecture — RP 서버 통합 권장 구조