Skip to content

Commit 74c74fb

Browse files
committed
feat: back the OAuth2 consent session with Spring Session JDBC
The auth-code consent flow needs an HttpSession to carry the authenticated principal from /oauth2/session-bootstrap into /oauth2/authorize. Storing it in JDBC (Spring Session) keeps it shared across replicas so the app stays otherwise stateless; the schema is managed by Liquibase, not Spring Session.
1 parent 41706a3 commit 74c74fb

5 files changed

Lines changed: 61 additions & 1 deletion

File tree

backend/app/src/main/resources/application.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ spring:
88
redis:
99
repositories:
1010
enabled: false
11+
session:
12+
# JDBC-backed HTTP sessions (shared across replicas) for the OAuth2 consent flow; the app is otherwise stateless.
13+
# The schema is created by Liquibase (db/changelog/spring-session), not by Spring Session.
14+
store-type: jdbc
15+
jdbc:
16+
initialize-schema: never
1117
mvc:
1218
pathmatch:
1319
matching-strategy: ant_path_matcher

backend/data/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,9 @@ dependencies {
184184
implementation libs.jjwtImpl
185185
implementation libs.jjwtJackson
186186
api libs.springSecurityOauth2AuthServer
187+
// Shared JDBC session store so the OAuth2 consent flow's HttpSession survives across replicas (the app is
188+
// otherwise stateless). See db/changelog/spring-session/spring-session.xml for the schema.
189+
api 'org.springframework.session:spring-session-jdbc'
187190
implementation libs.jacksonModuleKotlin
188191
implementation 'net.datafaker:datafaker:2.4.4'
189192
implementation 'jaxen:jaxen:1.2.0'

backend/data/src/main/resources/db/changelog/schema.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5877,4 +5877,5 @@
58775877
</sql>
58785878
</changeSet>
58795879
<include file="db/changelog/oauth2/oauth2-server.xml"/>
5880+
<include file="db/changelog/spring-session/spring-session.xml"/>
58805881
</databaseChangeLog>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
2+
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.20.xsd">
5+
6+
<!--
7+
Spring Session JDBC schema (spring-session-jdbc). Backs the OAuth2 consent flow's HttpSession with the shared
8+
Postgres so the bootstrapped SecurityContext is visible on any replica. Source: classpath resource
9+
org/springframework/session/jdbc/schema-postgresql.sql. These tables are NOT JPA entities, so they are listed in
10+
gradle/liquibase.gradle excludeObjects. spring.session.jdbc.initialize-schema=never leaves creation to us.
11+
-->
12+
13+
<changeSet author="dbocharov" id="spring-session">
14+
<sql dbms="postgresql" splitStatements="false">
15+
CREATE TABLE SPRING_SESSION (
16+
PRIMARY_ID CHAR(36) NOT NULL,
17+
SESSION_ID CHAR(36) NOT NULL,
18+
CREATION_TIME BIGINT NOT NULL,
19+
LAST_ACCESS_TIME BIGINT NOT NULL,
20+
MAX_INACTIVE_INTERVAL INT NOT NULL,
21+
EXPIRY_TIME BIGINT NOT NULL,
22+
PRINCIPAL_NAME VARCHAR(100),
23+
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
24+
);
25+
26+
CREATE UNIQUE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
27+
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME);
28+
CREATE INDEX SPRING_SESSION_IX3 ON SPRING_SESSION (PRINCIPAL_NAME);
29+
30+
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
31+
SESSION_PRIMARY_ID CHAR(36) NOT NULL,
32+
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
33+
ATTRIBUTE_BYTES BYTEA NOT NULL,
34+
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
35+
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID)
36+
REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
37+
);
38+
</sql>
39+
<rollback>
40+
<sql>
41+
DROP TABLE SPRING_SESSION_ATTRIBUTES;
42+
DROP TABLE SPRING_SESSION;
43+
</sql>
44+
</rollback>
45+
</changeSet>
46+
47+
</databaseChangeLog>

gradle/liquibase.gradle

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ ext {
4343
// Spring Authorization Server tables (not JPA entities): managed by db/changelog/oauth2/oauth2-server.xml
4444
"table:oauth2_registered_client,"+
4545
"table:oauth2_authorization,"+
46-
"table:oauth2_authorization_consent"
46+
"table:oauth2_authorization_consent,"+
47+
// Spring Session tables (not JPA entities): managed by db/changelog/spring-session/spring-session.xml
48+
"table:spring_session,"+
49+
"table:spring_session_attributes"
4750
}
4851
}
4952
}

0 commit comments

Comments
 (0)