웹3 세상에서는 개인이 identity와 data에 대한 통제권을 갖습니다. 그래서 웹3 세상을 열기 위해서는 identity와 data 관리에 대한 고민이 필수적입니다. 그런 맥락에서 현실 세계의 대표적인 identity 관리 방식인 OAuth2와 OpenID Connect을 살펴봅니다.
OAuth2 표준과 OpenID Connect 표준
OAuth2는 Authorization(이후 authZ)에 대한 표준이다.
반면 OpenID Connect(이후 OIDC)는 Authentication(이후 authN)에 대한 표준이다.
OIDC 표준은 OAuth2 표준을 기반으로 정의되었다.
OIDC AuthZ code flow
그림1. OAuth2 시퀀스
그림2. OIDC 시퀀스
그림1은 OAuth2 authZ code grant type의 동작 시퀀스다.
그림2는 OIDC authZ code flow의 동작 시퀀스다.
두 시퀀스는 사실상 동일하다. 두 시퀀스의 차이점은 id-provider 서버(그림의 'KEYCLOAK')로부터 받아 오는 토큰이다(양쪽 그림의 5번 'Exchange authZ code...' 화살표).
이때 OAuth2 프로토콜은 Access Token을 발급하고, OIDC 프로토콜은 ID Token을 발급한다.
OIDC JWT 표준
ID Token의 규격은 OIDC 표준이 정한다.
ID Token은 JWT(JSON Web Token) 포맷을 따른다.
JWT 토큰에는 토큰 발급자(issuer, 이후 iss)의 priv-key를 이용해서 만든 서명이 포함되어 있어서, 누구나 iss의 pub-key를 이용해서 토큰의 무결성을 검증할 수 있다.
Access Token 관련해서는 정해진 규격이 없다.
OAuth2 표준은 Access Token의 포맷을 규정하지 않는다. 그래서 어떤 포맷을 사용하더라도 표준에 부합한다.
JWT 토큰에 포함된 Signature는 iss의 priv-key를 이용해 만들어진 값이다.
이를 검증하려면 iss의 pub-key가 필요하다.
그런데 JWT 토큰 안에는 iss의 pub-key가 존재하지 않는다. 어디서 가져왔을까?
JWKS URI
JWT 토큰을 검증하려면 iss의 pub-key를 확보해야 한다. 그 절차는 다음과 같다.
토큰에 포함된 iss 속성값으로부터 well-known URL을 유추한다 (iss + '/.well-known/openid-configuration').
(예시로 든 토큰샘플의 iss는 http://localhost:8380 이다. 이 토큰을 검증해서 Signature Verified 결과를 얻으려면 http://localhost:8380/.well-known/openid-configuration 엔드포인트를 호스팅하는 id-provider가 떠 있어야 한다.)
npm init vue@latest명령으로 Vue3와 Pinia를 이용하는 웹앱의 뼈대를 만듭니다.
$ node -v
v16.20.0
$ npm init vue@latest
Vue.js - The Progressive JavaScript Framework
✔ Project name: … todo
✔ Add TypeScript? … No
✔ Add JSX Support? … No
✔ Add Vue Router for Single Page Application development? … No
✔ Add Pinia for state management? … Yes
✔ Add Vitest for Unit Testing? … Yes
✔ Add an End-to-End Testing Solution? › No
✔ Add ESLint for code quality? … No
Scaffolding project in /home/ingee/work/todo/todo...
Done. Now run:
cd todo
npm install
npm run dev
1. Pinia 스토어에 있는 todo 목록을 화면에 표시하자
목표
Pinia 스토어에 todos라는 이름으로 todo 목록을 저장할 계획입니다.
Pinia 스토어에 저장되어 있는 todo 목록을 화면에 표시하는 기능부터 구현하기로 합니다.
Pinia의 초기 상태로 지정한 todo 목록이 화면에 표시되지 않는다고 합니다. 적절합니다.
❯ src/__tests__/App.spec.js (1)
❯ App.vue (1)
× shows todos in store
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
FAIL src/__tests__/App.spec.js > App.vue > shows todos in store
AssertionError: expected 'Todo Lorem Ipsum is simply dummy text…' to include 'wake up'
❯ src/__tests__/App.spec.js:35:30
33| const wrapper = createWrapper({ initialState })
34| for (const todo of todos) {
35| expect(wrapper.text()).toContain(todo)
| ^
36| }
37| })
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Test Files 1 failed (1)
Tests 1 failed (1)
Start at 13:08:02
Duration 90ms
FAIL Tests failed. Watching for file changes...
press h to show help, press q to quit
✓ src/__tests__/App.spec.js (1)
Test Files 1 passed (1)
Tests 1 passed (1)
Start at 13:11:57
Duration 108ms
PASS Waiting for file changes...
press h to show help, press q to quit
2. 입력창에 입력한 todo를 Pinia 스토어에 저장하자
목표
화면에 입력한 todo를 Pinia 스토어에 저장할 계획입니다.
todo를 입력하고 Add 버튼을 클릭하면, 해당 항목이 Pinia 스토어에 저장되게 하기로 합니다.
✓ src/__tests__/App.spec.js (2)
Test Files 1 passed (1)
Tests 2 passed (2)
Start at 13:45:47
Duration 160ms
PASS Waiting for file changes...
press h to show help, press q to quit
트위터를 즐겨 쓴다. 나름 헤비 유저다. 트위터는 옛날부터 키보드 사용자를 배려해왔다. 트위터 화면에서 J,K 키를 입력하면 화면을 아래,위로 스크롤할 수 있다. VIM 사용자 입장에서 아주 자연스럽고 쾌적하다. 그런데 가끔 딱 시야를 방해하는 그 자리에 "새 트윗 보기" 팝업이 뜬다. 일단 팝업이 뜨면 가독성이 현격히 떨어진다. 쾌적하지 못하다.
그림 : 문제 현상
해결책을 찾기 위해 노력했다. 브라우저 개발자 도구를 열고 범인을 찾았다. 그리고 해당 html 요소를 투명하게 만들면 해결 가능함을 확인했다. 하지만 트위터를 켤 때마다 개발자 도구를 열고 콘솔창에서 "화면 청소 코드"를 실행시키는 것은 사람이 할 짓이 아니었다. 이런 건 분명 기계에게 시켜야 옳은 일이다. 그리고 나만 불편할까? 이 기능을 브라우저 애드온으로 만들어 공개한다면 널리 세상을 이롭게 하는, 단군 할아버지께서 기뻐하실 만한 일이 되지 않을까?
그림 : 범인
해결책 : 트위터 화면 청소 코드
obj = document.getElementsByClassName('r-dkhcqf'); for (o of obj) { o.style.opacity = 0.1 }
참조 코드를 찾자
모방은 창조의 어머니. 가장 먼저 할 일은 참조 코드를 찾는 일이다. 파이어폭스를 주력 브라우저로 쓰는 입장에서 아주 그럴듯한 참조 코드를 찾았다.webextensions-examples. 이름처럼 다양한 애드온 샘플로 구성된 프로젝트다. 제시된 애드온 샘플 중에서 borderify 샘플이 내게 잘 맞는다고 생각했다. borderify 애드온은 *.mozilla.org 페이지를 표시할 때마다 붉은색 테두리를 덧붙여 표시하는 애드온이다. 특정 url에 반응한다는 점(즉 트위터 url에 반응하는 애드온을 만들 수 있다는 점)과 브라우저 컨텐트를 대상으로 스크립트를 실행한다는 점(즉 트위터 화면 청소 코드를 실행시키는 애드온을 만들 수 있다는 점)이 내가 원하던 바였다.
파이어폭스 주소창에서 about:debugging을 입력하고, "임시 부가 기능 로드..." 버튼을 선택해서 manifest.json 파일을 선택하면, 브라우저에서 애드온을 실행시켜 볼 수 있다. 그렇게 애드온이 정상 동작함을 확인했다.
그림 : 애드온 개발 설정
이제 개발한 애드온을 정식 등록할 차례다. 그러면 브라우저를 실행시킬 때마다 "임시 부가 기능 로드..." 버튼을 클릭하지 않아도 된다. 그리고 집에 있는 컴퓨터 뿐 아니라 회사에 있는 컴퓨터에서도 이 애드온을 사용할 수 있게 된다. 절차는 간단했다.AMO 개발자 허브에 등록하면 된다. 소스 코드를 zip 파일로 압축해서 클릭 몇 번만 하면 등록이 완료된다. 그러면 24 시간 이내에 처리 결과를 알려주겠다는 친절한 메일이 온다. 그리고 정말 그 다음날 애드온이 등록됐다.
그림 : AMO에 정식 등록된 애드온
그림 : 파이어폭스에 정식 설치된 애드온
브라우저 애드온은 나름 표준 웹기술이어서 파이어폭스 애드온을 조금만 다듬으면 크롬 브라우저에서도 사용 가능하다. 크롬 브라우저를 위한 나머지 일은 다른 훌륭한 사람에게 미룬다. 브라우저로 할 수 있는 재미난 일이 더욱 많아지기를 희망한다.웹3 세상의 주력 플랫폼은 브라우저일 것이다.