security

47 posts
Passport.js로 Bearer 토큰 기반 API 인증 구현하기

Passport.js로 Bearer 토큰 기반 API 인증 구현하기

이번 포스팅에서는 Passport.js라는 자바스크립트 프레임워크를 사용하여 Bearer 토큰 기반 API 인증을 구현해보겠습니다. 본 포스팅의 예제 코드는 ES 모듈 문법을 사용하여 작성되었습니다. Node.js에서 ES 모듈을 사용하는 방법은 별도 포스팅에서 자세히 다루고 있으니 참고 바랍니다. Bearer 토큰이란? Bearer 토큰은 HTTP 요청에서 인증 정보를 전달하는 방법으로 클라이언트가 서버에 접근할 때 인증을 위해 널리 사용됩니다. 일반적으로 클라이언트가 서버에 요청을 보낼 때 HTTP 요청의 Authorizatio

자바스크립트로 JWT 토큰을 발급하고 검증하기

자바스크립트로 JWT 토큰을 발급하고 검증하기

이번 포스팅에서는 자바스크립트로 어떻게 JWT 토큰을 발급하고 검증하는지에 대해서 알아보겠습니다. jsonwebtoken 패키지 설치 우선 Node.js의 패키지 매니저인 npm을 이용하여 jsonwebtoken 패키지를 설치하겠습니다. jsonwebtoken는 JWT 표준 명세서를 자바스크립트 언어로 구현하고 있는 라이브러리입니다. 따라서 JWT 기반으로 사용자 인증이나 인가를 하는 자바스크립트 서버 애플리케이션에서는 직접적으로든 간접적으로든 (passport-jwt와 같은 프레임워크를 통해서) jsonwebtoken 라이브러리를

JWT - Json Web Token

JWT - Json Web Token

이번 포스팅에서는 Json Web Token, 줄여서 흔히 JWT라고 불리는 사용자 인증/인가 수단 대해서 알아보도록 하겠습니다. JWT 란? JWT(Json Web Token)는 말그대로 웹에서 사용되는 JSON 형식의 토큰에 대한 표준 규격인데요. RFC 7519로 정의되어 있으며, 토큰을 어떤 구조로 만들고 어떻게 서명하는지, 그리고 안에 담을 수 있는 표준 클레임(claim)에는 어떤 것들이 있는지를 규정합니다. 주로 사용자의 인증(authentication) 또는 인가(authorization) 정보를 서버와 클라이언트 간

JWE로 JSON 데이터 암호화하기

JWE로 JSON 데이터 암호화하기

JWS로 이해하는 JSON 데이터 서명에서 서명이 토큰의 위변조를 막아준다는 걸 봤는데요. 한 가지 짚고 넘어간 점이 있습니다. 서명은 내용을 숨겨주지 않는다는 것이죠. JWS나 JWT의 페이로드는 그냥 Base64로 인코딩됐을 뿐이라 누구나 디코딩해서 들여다볼 수 있습니다. 그렇다면 토큰 내용 자체를 진짜로 가려야 할 때는 어떻게 할까요? 이때 등장하는 것이 **JWE(JSON Web Encryption)**입니다. 이번 글에서는 JWE가 JWS와 무엇이 다른지, 독특한 5조각 구조와 2단계 암호화 방식이 무엇인지를 직접 암호화/

JWT 서명 알고리즘 비교: HS256 vs RS256 vs ES256

JWT 서명 알고리즘 비교: HS256 vs RS256 vs ES256

JWT나 JWS로 토큰에 서명하려고 보면 alg 자리에 뭘 넣어야 할지부터 막히는데요. HS256, RS256, ES256, EdDSA... 이름은 비슷비슷한데 막상 고르려니 뭐가 다른지 감이 안 옵니다. 🤔 이 알고리즘들은 모두 JWA(JSON Web Algorithms, RFC 7518)가 정의한 서명 알고리즘인데요. 그냥 아무거나 골라도 토큰은 만들어지지만, 대칭이냐 비대칭이냐, 토큰이 얼마나 커지느냐, 검증 부하가 어디에 실리느냐에 따라 분명한 트레이드오프가 있습니다. 이번 글에서는 자주 쓰이는 네 가지를 비교하고 상황별로

JWS로 이해하는 JSON 데이터 서명

JWS로 이해하는 JSON 데이터 서명

JWT를 한 번이라도 디코딩해 본 적이 있다면 header.payload.signature처럼 점으로 나뉜 세 조각을 기억하실 텐데요. 앞의 두 조각은 그냥 Base64로 인코딩된 JSON이라 누구나 열어볼 수 있지만, 마지막 서명(signature) 조각이 있어서 토큰의 위변조를 잡아낼 수 있습니다. 그런데 이 서명, 사실 JWT만의 것이 아닙니다. **JWS(JSON Web Signature)**라는 별도의 표준이 있고, JWT는 그 위에 얹힌 한 가지 응용일 뿐인데요. 이번 글에서는 JWS가 정확히 무엇이고 어떻게 데이터에 서

JOSE 한눈에 보기: JWT를 떠받치는 표준 가족

JOSE 한눈에 보기: JWT를 떠받치는 표준 가족

JWT는 익숙한데 JWS, JWE, JWK, JWA까지 줄줄이 나오면 갑자기 머리가 복잡해지는데요. 이름도 비슷하고 죄다 eyJ로 시작하는 긴 문자열을 다루는 것 같은데, 도대체 뭐가 뭔지 경계가 흐릿합니다. 🤔 사실 이 다섯은 JOSE라는 한 가족입니다. 서로 다른 일을 맡은 형제들이 모여 "JSON으로 데이터를 안전하게 주고받는다"는 하나의 목표를 이루는 구조죠. 이 글은 JOSE 가족의 큰 그림을 그리고, 각 멤버가 무슨 역할을 하며 어떻게 맞물리는지, 그리고 더 깊이 알고 싶을 때 어느 글로 가면 되는지를 안내하는 지도 역

쿠키 2부: 세션은 쿠키가 필요해~

쿠키 2부: 세션은 쿠키가 필요해~

“사용자 인증을 할 때 쿠키를 사용하면 위험하고요 서버에 데이터를 저장하는 세션을 사용하는 것이 안전해요.” 사용자 인증에 대해서 논할 때 자주 듣게 되는 얘기인데요. 과연 이 말이 맞는 말일까요? 저한테는 굉장히 모순된 얘기로 들리는 것 같습니다. 많은 분들이 쿠키(cookie)와 세션(session)을 서로 대립하거나 세션이 쿠키를 대체하는 기술로 오해하는 것 같은데요. 사실 쿠키와 세션은 상호 보완을 하는 기술이라고 보는 것이 더 맞을 것입니다. 지난 포스팅에서는 서버가 브라우저에 쿠키를 어떻게 저장하고 쿠키라는 기술의 한계에

쿠키 1부: HTTP로 설명하는 쿠키(cookie)

쿠키 1부: HTTP로 설명하는 쿠키(cookie)

"쿠키는 클라이언트에 저장되고... 음,,, 보안에 좋지 않습니다." 😅 개발자 면접을 볼 때 쿠키에 대해서 물어보면 가장 흔하게 들을 수 있는 대답인데요. 완전히 틀린 말은 아니지만 뭔가 알맹이가 빠진 느낌이 듭니다. 쿠키가 왜 등장했는지를 이해하려면 HTTP가 무상태(stateless) 프로토콜이라는 점을 먼저 떠올려보면 좋습니다. "그럼 보안을 위해서 쿠키는 안 쓰는 게 좋겠네요?" 라고 반문을 하면 오랫동안 웹 개발을 한 분들도 머뭇거리시는 경우가 많은데요. 아무래도 대부분의 서버 프레임워크에서 쿠키를 직접 다루지 않아도

SSH란 무엇인가: 원격 접속과 공개 키 인증의 원리

SSH란 무엇인가: 원격 접속과 공개 키 인증의 원리

클라우드에 서버를 하나 만들고 나면 대개 이런 명령어부터 입력하게 됩니다. 명령어 한 줄로 멀리 있는 서버의 터미널이 열리니 무척 간단해 보이는데요. 처음 접속할 때 나타나는 지문이 무엇인지, 비밀번호 없이 어떻게 로그인이 되는지, ~/.ssh에는 왜 여러 파일이 생기는지 파고들기 시작하면 이야기가 금세 복잡해집니다. SSH를 단순히 원격 접속 명령어로만 외우면 연결 오류가 났을 때 어디부터 확인해야 할지 막막합니다. 반대로 서버 확인과 사용자 인증을 구분해서 이해하면 키를 안전하게 관리하는 방법도 자연스럽게 보이죠. 이번 글에서는

Caddy: 인증서를 신경 쓰지 않아도 되는 웹 서버

Caddy: 인증서를 신경 쓰지 않아도 되는 웹 서버

사이드 프로젝트를 서버에 처음 올려본 사람이라면 비슷한 밤을 보냈을 겁니다. 앱은 이미 3000번 포트에서 잘 돌아갑니다. 정작 반나절이 날아가는 쪽은 그걸 바깥에서 접속하게 만드는 일이죠. Nginx 설정 파일에서 server 블록과 location 블록의 중괄호를 세어 보고, Let's Encrypt 인증서를 받으려고 certbot을 깔고, 갱신이 제대로 도는지 확인하려고 cron 로그를 뒤지는 식입니다. 서비스 로직은 한 줄도 건드리지 않았는데 말이죠. 😅 Caddy는 바로 이 지점을 겨냥한 웹 서버입니다. Go로 작성된 오

구글 OpenID Connect 사용법

구글 OpenID Connect 사용법

최근에는 아이디와 비밀번호 입력없이도 구글이나 페이스북과 같은 대형 플랫폼을 통해서 로그인 할 수 있는 서비스들을 많이 볼 수 있습니다. 이번 포스팅에서는 이렇게 사용자 인증을 다른 서비스에 위임하기 위해서 사용되는 프로토콜인 OpenID Connect에 대해서 알아보겠습니다. OpenID Connect란? 예전에는 사용자 데이터를 서비스에서 직접 관리하는 경우가 많았지만, 개인 정보가 유출되는 보안 사고가 잇달아 발생함에 따라, 요즘에는 사용자 데이터를 자체적으로 보관하는 것 자체가 부담스러운 작업이 되어가고 있습니다. 이 때문에

OAuth 2.0으로 구글 API 호출하기

OAuth 2.0으로 구글 API 호출하기

검색과 지메일, 연락처, 캘린더, 드라이브, 포토, 유튜브 등 우리는 거의 매일 구글의 서비스를 이용하면서 살고 있다고 해도 과언이 아니죠? 구글은 이렇게 다양한 제품에 걸쳐서 관리되고 있는 데이터를 사용자의 허락을 받고 접근할 수 있도록 Google APIs를 제공하고 있는데요. 이번 글에서는 OAuth 2.0을 통해 사용자의 동의를 구하고 구글 API를 호출하는 방법에 대해서 알아보겠습니다. OAuth 2.0이란? 먼저 OAuth 2.0이 생소하신 분을 위해서, 과연 OAuth 2.0가 무엇인지 간단하게 개념부터 짚고 가겠습니다

PKCE로 Authorization Code 흐름 안전하게 보호하기

PKCE로 Authorization Code 흐름 안전하게 보호하기

OAuth 2.0의 인가 코드(Authorization Code) 흐름을 처음 구현해보면, 어딘가 찜찜한 부분이 있습니다. 서버가 있는 웹 애플리케이션이라면 client secret을 안전하게 숨겨둘 수 있는데, 모바일 앱이나 SPA(Single Page Application)는 어디에 숨겨야 할까요? 🤔 APK를 디컴파일하거나 브라우저 개발자 도구를 열면 그대로 노출되니, 사실상 비밀이 아닌 셈입니다. PKCE(Proof Key for Code Exchange, "픽시"라고 읽습니다)는 바로 이 문제를 해결하기 위해 만들어진 보

OAuth 2.0 쉽게 이해하기

OAuth 2.0 쉽게 이해하기

내 서비스에서 구글 캘린더에 있는 사용자의 일정을 가져와야 한다면 어떻게 해야 할까요? 사용자에게 구글 이메일과 비밀번호를 알려달라고 할 수도 없고, 직접 구글 캘린더에서 일정을 내려받아 달라고 할 수도 없겠죠 😅 OAuth 2.0은 바로 이런 문제를 해결하기 위해 만들어진 프로토콜입니다. 사용자의 비밀번호를 직접 받지 않고도, 사용자가 명시적으로 동의한 범위 내에서 데이터에 접근할 수 있는 표준화된 방법을 제공하는데요. 이번 글에서는 OAuth 2.0의 기본 개념부터 인가 코드(Authorization Code) 흐름까지 차근차

CSRF(Cross-Site Request Forgery) 공격과 방어

CSRF(Cross-Site Request Forgery) 공격과 방어

쇼핑 사이트에 로그인한 상태로 다른 탭에서 별 생각 없이 열어본 기사 링크 하나가, 내 계정에서 100만 원짜리 상품 주문을 자동으로 날려버릴 수 있다면 믿어지시나요? 바로 이게 CSRF(Cross-Site Request Forgery) 공격의 본질입니다. "사이트 간 요청 위조"라는 이름 그대로, 공격자가 내 브라우저를 통해 내 이름으로 요청을 보내는 공격이에요. 이 글에서는 CSRF가 왜 가능한지, 공격이 실제로 어떻게 성립하는지, 그리고 이를 막는 네 가지 방어 기법(Synchronizer Token, Double Submit

소스맵(Source Map) 완전 해부

소스맵(Source Map) 완전 해부

브라우저 개발자 도구에서 Sources 패널을 열어보면 원본 TypeScript 파일이 깔끔하게 표시되곤 합니다. 분명 브라우저가 실행하는 건 번들링되고 압축된 JavaScript일 텐데, 어떻게 원본 코드가 나타나는 걸까요? 바로 소스맵(source map) 덕분이에요. 소스맵은 웹 개발에서 빠질 수 없는 디버깅 도구지만 그 내부를 들여다볼 일은 좀처럼 없는데요. 이 글에서는 소스맵의 JSON 구조와 VLQ 인코딩 원리를 깊이 살펴보고 주요 빌드 도구별 설정 방법도 정리해보겠습니다. 나아가 프로덕션 환경에서 소스맵이 뜻하지 않게

TLS 핸드셰이크: 대칭키, 비대칭키, 해시는 어떻게 만날까

TLS 핸드셰이크: 대칭키, 비대칭키, 해시는 어떻게 만날까

대칭키 암호화는 빠르지만 비밀 키를 안전하게 나누기 어렵습니다. 비대칭키 암호화는 처음 만난 상대와 비밀을 합의하고 신원을 증명할 수 있지만, 큰 데이터를 처리하기에는 무겁죠. 암호학적 해시 함수는 메시지가 달라졌는지를 짧은 값으로 드러내고 키를 여러 용도로 나누는 재료가 됩니다. 따로 배운 세 도구가 실제 인터넷에서는 어떻게 한자리에 모일까요? 가장 친숙한 답이 전송 계층 보안(Transport Layer Security, TLS)입니다. HTTPS로 웹사이트에 접속하면 브라우저와 서버는 TLS 핸드셰이크를 거쳐 서로를 확인하고,

디지털 서명이란 무엇인가: 개인 키로 서명하고 공개 키로 검증하는 원리

디지털 서명이란 무엇인가: 개인 키로 서명하고 공개 키로 검증하는 원리

인터넷에서 받은 프로그램이 개발자가 배포한 그대로인지, 로그인 요청이 정말 등록된 기기에서 왔는지, 웹사이트가 접속하려던 서버가 맞는지는 어떻게 확인할까요? 내용을 암호화하면 제삼자가 읽지 못하게 숨길 수는 있지만 누가 만들었고 중간에서 바뀌지 않았는지까지 저절로 증명되지는 않습니다. 이때 사용하는 도구가 디지털 서명(digital signature)입니다. 디지털 서명은 종이에 하는 서명처럼 데이터에 신원을 연결하지만 눈으로 필체를 비교하는 대신 개인 키와 공개 키를 사용해 수학적으로 검증하는데요. TLS의 서버 인증, JWS와

HMAC이란 무엇인가: 비밀 키로 메시지를 인증하는 원리

HMAC이란 무엇인가: 비밀 키로 메시지를 인증하는 원리

결제 서비스가 우리 서버로 다음과 같은 웹훅(webhook)을 보냈다고 해볼까요? HTTPS로 받았으니 무조건 믿고 결제 완료 처리를 해도 될까요? HTTPS는 전송 구간을 보호하지만, 이 요청이 정말 결제 서비스가 만든 것인지 애플리케이션이 확인할 방법은 따로 필요합니다. 공격자가 우리 웹훅 주소를 알아내고 가짜 요청을 직접 보낼 수도 있으니까요. 메시지의 SHA-256 해시를 함께 받으면 해결될 것 같지만, 공격자는 가짜 메시지의 해시도 다시 계산할 수 있습니다. 누구나 계산할 수 있는 해시만으로는 메시지를 만든 상대를 가려낼

Discord