SniffMEET. anon-key와 익명 사용자의 접근 권한 구분

anon-role과 anon-user의 접근 권한 차이 Public Scheme에 있는 테이블을 anon-key로는 접근할 수 있었지만, anon-user의 JWT 토큰으로는 접근하지 못하는 문제가 있었다. 처음에는 둘이 비슷한 범주라고 생각했지만, 실제로는 권한 체계와 접근 방식이 달라서 같은 문제로 볼 수 없었다. 문제를 확인하기 전 생각한 내용 anon-key, anon-role, anon-user의 차이부터 다시 정리했다. anon-key를 이용한 접근은 anon-role로 보고, anon-user는 이메일 주소나 전화번호를 등록하지 않은 유저를 의미한다. 이 경우 role 자체는 authenticated-role이었다. 익명 유저가 접근했을 때 200 OK가 뜨지만 실제 값을 가져오지 못하는 경우도 있었다. 그래서 접근 자체는 허용되지만 RLS에서 막히고 있다고 추정할 수 있었다. ...

November 28, 2024

SniffMEET. Storage 버킷과 접근 제어

SniffMEET의 프로필 이미지는 사용자 정보와 성격이 다르다. 사용자 이름이나 소개처럼 구조화된 데이터는 Database에 저장하고, 이미지 파일은 Storage에 저장하는 편이 적합하다. Storage의 Postgres 테이블에는 파일 자체가 아니라 버킷과 객체의 메타데이터가 기록된다. 버킷과 객체 경로 버킷은 파일을 묶는 최상위 컨테이너다. 사용자마다 버킷을 만드는 것보다 용도별 버킷을 만들고 객체 경로로 사용자를 구분하는 편이 관리하기 쉽다. profile-images/ ├── {user-id}/profile.jpg └── {user-id}/thumbnail.jpg 이 구조에서는 profile-images 버킷이 공통된 공개 범위와 파일 제한을 담당하고, 사용자 ID가 포함된 경로를 RLS 정책에서 검사할 수 있다. ...

November 24, 2024

SniffMEET. RLS와 테이블 권한

문제 Supabase에서 anon key로 Public 테이블에 접근하면 데이터가 보이는데, 익명 로그인 후 받은 JWT access token으로 접근하면 200 OK만 오고 데이터가 비어 있었다. 처음에는 authenticated role이 anon role보다 상위 권한이라고 생각해서 더 헷갈렸다. 하지만 Supabase에서는 role의 상하관계보다 RLS 정책을 어떻게 작성했는지가 더 중요했다. 확인 JWT가 만료된 경우에는 401 Unauthorized가 발생했다. 반면 RLS 조건에 맞지 않는 경우에는 요청 자체는 성공해서 200 OK가 오지만, row가 필터링되어 데이터가 내려오지 않았다. authenticated 유저가 읽을 수 있도록 다음 policy를 추가하자 데이터를 읽을 수 있었다. ...

November 20, 2024

SniffMEET. JWT와 Supabase RLS 정책에 연결하기

Supabase Auth로 로그인하면 클라이언트는 Access Token으로 JWT를 받는다. Supabase는 요청에 포함된 JWT를 검증하고, 그 안의 사용자 정보와 역할을 RLS 정책에 전달한다. JWT의 클레임 JWT는 헤더, 페이로드, 서명으로 구성된다. 각 부분은 Base64URL로 인코딩되지만 암호화되지는 않으므로 페이로드에 비밀 정보를 넣으면 안 된다. 서명은 헤더와 페이로드가 변조되지 않았는지 검증하는 데 사용한다. Supabase의 JWT에는 다음과 같은 클레임이 포함된다. sub: 사용자의 고유 ID role: RLS를 적용할 PostgreSQL 역할 iat: 토큰이 발급된 시각 exp: 토큰이 만료되는 시각 Supabase에서 JWT 사용하기 RLS는 PostgreSQL이 행 단위로 접근을 제한하는 기능이다. Supabase에서는 auth.uid()로 현재 JWT의 sub 값을 가져와 행의 사용자 ID와 비교할 수 있다. ...

November 20, 2024