WIP: feat(security): implement refresh tokens #49

Closed
dylan wants to merge 25 commits from feat/add-refresh-tokens into master
3 changed files with 22 additions and 18 deletions
Showing only changes of commit 0c04bf4c97 - Show all commits

View File

@@ -2,6 +2,7 @@ package com.ddf.vodsystem.entities;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Data; import lombok.Data;
import org.hibernate.annotations.CreationTimestamp;
import java.time.Instant; import java.time.Instant;
@@ -11,19 +12,20 @@ import java.time.Instant;
public class RefreshToken { public class RefreshToken {
@Id @Id
@Column(name = "id", nullable = false, unique = true) @Column(name = "id", nullable = false, unique = true)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user;
@ManyToOne(fetch = FetchType.LAZY) @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "family_id", nullable = false) @JoinColumn(name = "family_id", nullable = false)
private TokenFamily tokenFamily; private TokenFamily tokenFamily;
@Column(name = "token_hash", unique = true, nullable = false) @Column(name = "token_hash", unique = true, nullable = false, length = 32)
private byte[] tokenHash; private byte[] tokenHash;
@Column(name = "created_at", nullable = false)
@CreationTimestamp
private Instant createdAt;
@Column(name = "expires_at", nullable = false) @Column(name = "expires_at", nullable = false)
private Instant expiresAt; private Instant expiresAt;

View File

@@ -2,6 +2,7 @@ package com.ddf.vodsystem.entities;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Data; import lombok.Data;
import org.hibernate.annotations.CreationTimestamp;
import java.time.Instant; import java.time.Instant;
@@ -11,12 +12,17 @@ import java.time.Instant;
public class TokenFamily { public class TokenFamily {
@Id @Id
@Column(name = "id", nullable = false, unique = true) @Column(name = "id", nullable = false, unique = true)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; private Long id;
@ManyToOne(fetch = FetchType.LAZY) @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false) @JoinColumn(name = "user_id", nullable = false)
private User user; private User user;
@Column(name = "created_at", nullable = false)
@CreationTimestamp
private Instant createdAt;
@Column(name = "expires_at", nullable = false) @Column(name = "expires_at", nullable = false)
private Instant expiresAt; private Instant expiresAt;

View File

@@ -1,11 +1,10 @@
CREATE TABLE IF NOT EXISTS token_families CREATE TABLE IF NOT EXISTS token_families
( (
id BIGSERIAL PRIMARY KEY NOT NULl, id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
user_id BIGSERIAL NOT NULL, user_id BIGINT NOT NULL REFERENCES users (id) ON DELETE CASCADE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
expires_at TIMESTAMPTZ NOT NULL, expires_at TIMESTAMPTZ NOT NULL,
revoked_at TIMESTAMPTZ, revoked_at TIMESTAMPTZ
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
); );
CREATE INDEX IF NOT EXISTS idx_token_families_user_id CREATE INDEX IF NOT EXISTS idx_token_families_user_id
@@ -13,18 +12,15 @@ CREATE INDEX IF NOT EXISTS idx_token_families_user_id
CREATE TABLE IF NOT EXISTS refresh_tokens CREATE TABLE IF NOT EXISTS refresh_tokens
( (
id BIGSERIAL PRIMARY KEY NOT NULL, id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
user_id BIGSERIAL NOT NULL, family_id BIGINT NOT NULL REFERENCES token_families (id) ON DELETE CASCADE,
family_id BIGSERIAL NOT NULL, token_hash BYTEA NOT NULL UNIQUE, -- unique automatically creates a B-tree index
token_hash BYTEA NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
expires_at TIMESTAMPTZ NOT NULL, expires_at TIMESTAMPTZ NOT NULL,
used_at TIMESTAMPTZ, used_at TIMESTAMPTZ,
revoked_at TIMESTAMPTZ, revoked_at TIMESTAMPTZ,
CONSTRAINT refresh_tokens_hash_len CHECK (octet_length(token_hash) = 32), CONSTRAINT refresh_tokens_hash_len CHECK (octet_length(token_hash) = 32)
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (family_id) REFERENCES token_families(id) ON DELETE CASCADE
); );
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_family_id CREATE INDEX IF NOT EXISTS idx_refresh_tokens_family_id