1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-08-07 17:03:01 +03:00

Prepare the storage layer for legacy refresh tkoens

This commit is contained in:
Quentin Gliech
2022-05-17 17:02:56 +02:00
parent 076d4b8d13
commit 33204b7cf8
4 changed files with 221 additions and 126 deletions

View File

@@ -0,0 +1 @@
-- Add down migration script here

View File

@@ -0,0 +1,50 @@
-- Copyright 2022 The Matrix.org Foundation C.I.C.
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
CREATE TABLE compat_sessions (
"id" BIGSERIAL PRIMARY KEY,
"user_id" BIGINT NOT NULL REFERENCES users (id) ON DELETE CASCADE,
"device_id" TEXT UNIQUE NOT NULL,
"created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
"deleted_at" TIMESTAMP WITH TIME ZONE
);
INSERT INTO compat_sessions (user_id, device_id, created_at, deleted_at)
SELECT user_id, device_id, created_at, deleted_at
FROM compat_access_tokens;
ALTER TABLE compat_access_tokens
ADD COLUMN "compat_session_id" BIGINT REFERENCES compat_sessions (id) ON DELETE CASCADE;
UPDATE compat_access_tokens
SET compat_session_id = compat_sessions.id
FROM compat_sessions
WHERE compat_sessions.device_id = compat_access_tokens.device_id;
ALTER TABLE compat_access_tokens
ALTER COLUMN "compat_session_id" SET NOT NULL,
DROP COLUMN "device_id",
DROP COLUMN "user_id",
DROP COLUMN "deleted_at",
ADD COLUMN "expires_after" INT;
CREATE TABLE compat_refresh_tokens (
"id" BIGSERIAL PRIMARY KEY,
"compat_session_id" BIGINT NOT NULL REFERENCES compat_sessions (id) ON DELETE CASCADE,
"compat_access_token_id" BIGINT REFERENCES compat_access_tokens (id) ON DELETE SET NULL,
"token" TEXT UNIQUE NOT NULL,
"next_token_id" BIGINT REFERENCES compat_refresh_tokens (id),
"created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now()
);

View File

@@ -1106,6 +1106,33 @@
}, },
"query": "\n DELETE FROM oauth2_access_tokens\n WHERE id = $1\n " "query": "\n DELETE FROM oauth2_access_tokens\n WHERE id = $1\n "
}, },
"893b23b2385594f6c878d000b336d3c897adcffed35ee51d7dfea650b75aa0cf": {
"describe": {
"columns": [
{
"name": "id",
"ordinal": 0,
"type_info": "Int8"
},
{
"name": "created_at",
"ordinal": 1,
"type_info": "Timestamptz"
}
],
"nullable": [
false,
false
],
"parameters": {
"Left": [
"Int8",
"Text"
]
}
},
"query": "\n INSERT INTO compat_sessions (user_id, device_id)\n VALUES ($1, $2)\n RETURNING id, created_at\n "
},
"9882e49f34dff80c1442565f035a1b47ed4dbae1a405f58cf2db198885bb9f47": { "9882e49f34dff80c1442565f035a1b47ed4dbae1a405f58cf2db198885bb9f47": {
"describe": { "describe": {
"columns": [ "columns": [
@@ -1331,34 +1358,6 @@
}, },
"query": "UPDATE user_sessions SET active = FALSE WHERE id = $1" "query": "UPDATE user_sessions SET active = FALSE WHERE id = $1"
}, },
"a741cb29c617fb2df97f9e4bc84dbf85ff3c02ac87066770291d7bc153451695": {
"describe": {
"columns": [
{
"name": "id",
"ordinal": 0,
"type_info": "Int8"
},
{
"name": "created_at",
"ordinal": 1,
"type_info": "Timestamptz"
}
],
"nullable": [
false,
false
],
"parameters": {
"Left": [
"Int8",
"Text",
"Text"
]
}
},
"query": "\n INSERT INTO compat_access_tokens (user_id, token, device_id)\n VALUES ($1, $2, $3)\n RETURNING id, created_at\n "
},
"a80c14ba82cfc29493048d9e9578ec5ca482c9228efc7c7212dae4fed86b8367": { "a80c14ba82cfc29493048d9e9578ec5ca482c9228efc7c7212dae4fed86b8367": {
"describe": { "describe": {
"columns": [], "columns": [],
@@ -1422,6 +1421,18 @@
}, },
"query": "\n SELECT \n u.id AS user_id, \n u.username AS user_username,\n ue.id AS \"user_email_id?\",\n ue.email AS \"user_email?\",\n ue.created_at AS \"user_email_created_at?\",\n ue.confirmed_at AS \"user_email_confirmed_at?\"\n FROM users u\n\n LEFT JOIN user_emails ue\n ON ue.id = u.primary_email_id\n\n WHERE u.username = $1\n " "query": "\n SELECT \n u.id AS user_id, \n u.username AS user_username,\n ue.id AS \"user_email_id?\",\n ue.email AS \"user_email?\",\n ue.created_at AS \"user_email_created_at?\",\n ue.confirmed_at AS \"user_email_confirmed_at?\"\n FROM users u\n\n LEFT JOIN user_emails ue\n ON ue.id = u.primary_email_id\n\n WHERE u.username = $1\n "
}, },
"af3d36161bc60593ba991a9652efca1f19a9c4b291966dd41c1883b9c303673a": {
"describe": {
"columns": [],
"nullable": [],
"parameters": {
"Left": [
"Text"
]
}
},
"query": "\n UPDATE compat_sessions\n SET deleted_at = NOW()\n FROM compat_access_tokens\n WHERE compat_access_tokens.token = $1\n AND compat_sessions.id = compat_access_tokens.id \n AND compat_sessions.deleted_at IS NULL\n "
},
"b0fec01072df856ba9cd8be0ecf7a58dd4709a0efca4035a2c6f99c43d5a12be": { "b0fec01072df856ba9cd8be0ecf7a58dd4709a0efca4035a2c6f99c43d5a12be": {
"describe": { "describe": {
"columns": [ "columns": [
@@ -1557,17 +1568,32 @@
}, },
"query": "\n UPDATE oauth2_refresh_tokens\n SET next_token_id = $2\n WHERE id = $1\n " "query": "\n UPDATE oauth2_refresh_tokens\n SET next_token_id = $2\n WHERE id = $1\n "
}, },
"c53f3f064920f8516a14b384760e2c30f18ab6f099e468cf019fb4eaa0547637": { "c2de0bb4b67834bd6dd8106c3fcf9874d0e9d1c5d54cbbedfa070dcd0b372475": {
"describe": { "describe": {
"columns": [], "columns": [
"nullable": [], {
"name": "id",
"ordinal": 0,
"type_info": "Int8"
},
{
"name": "created_at",
"ordinal": 1,
"type_info": "Timestamptz"
}
],
"nullable": [
false,
false
],
"parameters": { "parameters": {
"Left": [ "Left": [
"Int8",
"Text" "Text"
] ]
} }
}, },
"query": "\n UPDATE compat_access_tokens\n SET deleted_at = NOW()\n WHERE token = $1 AND deleted_at IS NULL\n " "query": "\n INSERT INTO compat_access_tokens (compat_session_id, token)\n VALUES ($1, $2)\n RETURNING id, created_at\n "
}, },
"d2f767218ec2489058db9a0382ca0eea20379c30aeae9f492da4ba35b66f4dc7": { "d2f767218ec2489058db9a0382ca0eea20379c30aeae9f492da4ba35b66f4dc7": {
"describe": { "describe": {
@@ -1699,86 +1725,6 @@
}, },
"query": "\n INSERT INTO users (username)\n VALUES ($1)\n RETURNING id\n " "query": "\n INSERT INTO users (username)\n VALUES ($1)\n RETURNING id\n "
}, },
"de1ed5db37e48382a38075247c001cf4d01b7eeff165aa3aa62bb21a3284d5b7": {
"describe": {
"columns": [
{
"name": "compat_access_token_id",
"ordinal": 0,
"type_info": "Int8"
},
{
"name": "compat_access_token",
"ordinal": 1,
"type_info": "Text"
},
{
"name": "compat_access_token_created_at",
"ordinal": 2,
"type_info": "Timestamptz"
},
{
"name": "compat_access_token_deleted_at",
"ordinal": 3,
"type_info": "Timestamptz"
},
{
"name": "compat_access_token_device_id",
"ordinal": 4,
"type_info": "Text"
},
{
"name": "user_id!",
"ordinal": 5,
"type_info": "Int8"
},
{
"name": "user_username!",
"ordinal": 6,
"type_info": "Text"
},
{
"name": "user_email_id?",
"ordinal": 7,
"type_info": "Int8"
},
{
"name": "user_email?",
"ordinal": 8,
"type_info": "Text"
},
{
"name": "user_email_created_at?",
"ordinal": 9,
"type_info": "Timestamptz"
},
{
"name": "user_email_confirmed_at?",
"ordinal": 10,
"type_info": "Timestamptz"
}
],
"nullable": [
false,
false,
false,
true,
false,
false,
false,
false,
false,
false,
true
],
"parameters": {
"Left": [
"Text"
]
}
},
"query": "\n SELECT\n ct.id AS \"compat_access_token_id\",\n ct.token AS \"compat_access_token\",\n ct.created_at AS \"compat_access_token_created_at\",\n ct.deleted_at AS \"compat_access_token_deleted_at\",\n ct.device_id AS \"compat_access_token_device_id\",\n u.id AS \"user_id!\",\n u.username AS \"user_username!\",\n ue.id AS \"user_email_id?\",\n ue.email AS \"user_email?\",\n ue.created_at AS \"user_email_created_at?\",\n ue.confirmed_at AS \"user_email_confirmed_at?\"\n\n FROM compat_access_tokens ct\n INNER JOIN users u\n ON u.id = ct.user_id\n LEFT JOIN user_emails ue\n ON ue.id = u.primary_email_id\n\n WHERE ct.token = $1\n AND ct.deleted_at IS NULL\n "
},
"df38de13e2f345175f9ef46b4ae2a4f6637dbf74bb28559da8f4d8969f411d14": { "df38de13e2f345175f9ef46b4ae2a4f6637dbf74bb28559da8f4d8969f411d14": {
"describe": { "describe": {
"columns": [ "columns": [
@@ -1929,6 +1875,86 @@
}, },
"query": "\n SELECT COUNT(*) as \"count!\"\n FROM user_sessions s\n WHERE s.user_id = $1 AND s.active\n " "query": "\n SELECT COUNT(*) as \"count!\"\n FROM user_sessions s\n WHERE s.user_id = $1 AND s.active\n "
}, },
"eb12b728e0d58f6bba1a20fbc9bd01f3a6cbae7e40961b39eac3b294609edf2f": {
"describe": {
"columns": [
{
"name": "compat_access_token_id",
"ordinal": 0,
"type_info": "Int8"
},
{
"name": "compat_access_token",
"ordinal": 1,
"type_info": "Text"
},
{
"name": "compat_access_token_created_at",
"ordinal": 2,
"type_info": "Timestamptz"
},
{
"name": "compat_session_deleted_at",
"ordinal": 3,
"type_info": "Timestamptz"
},
{
"name": "compat_session_device_id",
"ordinal": 4,
"type_info": "Text"
},
{
"name": "user_id!",
"ordinal": 5,
"type_info": "Int8"
},
{
"name": "user_username!",
"ordinal": 6,
"type_info": "Text"
},
{
"name": "user_email_id?",
"ordinal": 7,
"type_info": "Int8"
},
{
"name": "user_email?",
"ordinal": 8,
"type_info": "Text"
},
{
"name": "user_email_created_at?",
"ordinal": 9,
"type_info": "Timestamptz"
},
{
"name": "user_email_confirmed_at?",
"ordinal": 10,
"type_info": "Timestamptz"
}
],
"nullable": [
false,
false,
false,
true,
false,
false,
false,
false,
false,
false,
true
],
"parameters": {
"Left": [
"Text"
]
}
},
"query": "\n SELECT\n ct.id AS \"compat_access_token_id\",\n ct.token AS \"compat_access_token\",\n ct.created_at AS \"compat_access_token_created_at\",\n cs.deleted_at AS \"compat_session_deleted_at\",\n cs.device_id AS \"compat_session_device_id\",\n u.id AS \"user_id!\",\n u.username AS \"user_username!\",\n ue.id AS \"user_email_id?\",\n ue.email AS \"user_email?\",\n ue.created_at AS \"user_email_created_at?\",\n ue.confirmed_at AS \"user_email_confirmed_at?\"\n\n FROM compat_access_tokens ct\n INNER JOIN compat_sessions cs\n ON cs.id = ct.compat_session_id\n INNER JOIN users u\n ON u.id = cs.user_id\n LEFT JOIN user_emails ue\n ON ue.id = u.primary_email_id\n\n WHERE ct.token = $1\n AND cs.deleted_at IS NULL\n "
},
"ebf73a609e81830b16700d2c315fffa93fd85b2886e29f234d9953b18a9f72b5": { "ebf73a609e81830b16700d2c315fffa93fd85b2886e29f234d9953b18a9f72b5": {
"describe": { "describe": {
"columns": [], "columns": [],

View File

@@ -29,8 +29,8 @@ pub struct CompatAccessTokenLookup {
compat_access_token_id: i64, compat_access_token_id: i64,
compat_access_token: String, compat_access_token: String,
compat_access_token_created_at: DateTime<Utc>, compat_access_token_created_at: DateTime<Utc>,
compat_access_token_deleted_at: Option<DateTime<Utc>>, compat_session_deleted_at: Option<DateTime<Utc>>,
compat_access_token_device_id: String, compat_session_device_id: String,
user_id: i64, user_id: i64,
user_username: String, user_username: String,
user_email_id: Option<i64>, user_email_id: Option<i64>,
@@ -71,8 +71,8 @@ pub async fn lookup_active_compat_access_token(
ct.id AS "compat_access_token_id", ct.id AS "compat_access_token_id",
ct.token AS "compat_access_token", ct.token AS "compat_access_token",
ct.created_at AS "compat_access_token_created_at", ct.created_at AS "compat_access_token_created_at",
ct.deleted_at AS "compat_access_token_deleted_at", cs.deleted_at AS "compat_session_deleted_at",
ct.device_id AS "compat_access_token_device_id", cs.device_id AS "compat_session_device_id",
u.id AS "user_id!", u.id AS "user_id!",
u.username AS "user_username!", u.username AS "user_username!",
ue.id AS "user_email_id?", ue.id AS "user_email_id?",
@@ -81,13 +81,15 @@ pub async fn lookup_active_compat_access_token(
ue.confirmed_at AS "user_email_confirmed_at?" ue.confirmed_at AS "user_email_confirmed_at?"
FROM compat_access_tokens ct FROM compat_access_tokens ct
INNER JOIN compat_sessions cs
ON cs.id = ct.compat_session_id
INNER JOIN users u INNER JOIN users u
ON u.id = ct.user_id ON u.id = cs.user_id
LEFT JOIN user_emails ue LEFT JOIN user_emails ue
ON ue.id = u.primary_email_id ON ue.id = u.primary_email_id
WHERE ct.token = $1 WHERE ct.token = $1
AND ct.deleted_at IS NULL AND cs.deleted_at IS NULL
"#, "#,
token, token,
) )
@@ -99,8 +101,8 @@ pub async fn lookup_active_compat_access_token(
data: res.compat_access_token_id, data: res.compat_access_token_id,
token: res.compat_access_token, token: res.compat_access_token,
created_at: res.compat_access_token_created_at, created_at: res.compat_access_token_created_at,
deleted_at: res.compat_access_token_deleted_at, deleted_at: res.compat_session_deleted_at,
device_id: res.compat_access_token_device_id, device_id: res.compat_session_device_id,
}; };
let primary_email = match ( let primary_email = match (
@@ -174,19 +176,32 @@ pub async fn compat_login(
.instrument(tracing::info_span!("Verify hashed password")) .instrument(tracing::info_span!("Verify hashed password"))
.await??; .await??;
let res = sqlx::query_as!( let session = sqlx::query_as!(
IdAndCreationTime, IdAndCreationTime,
r#" r#"
INSERT INTO compat_access_tokens (user_id, token, device_id) INSERT INTO compat_sessions (user_id, device_id)
VALUES ($1, $2, $3) VALUES ($1, $2)
RETURNING id, created_at RETURNING id, created_at
"#, "#,
user.data, user.data,
token,
device_id, device_id,
) )
.fetch_one(&mut txn) .fetch_one(&mut txn)
.await .await
.context("could not insert compat session")?;
let res = sqlx::query_as!(
IdAndCreationTime,
r#"
INSERT INTO compat_access_tokens (compat_session_id, token)
VALUES ($1, $2)
RETURNING id, created_at
"#,
session.id,
token,
)
.fetch_one(&mut txn)
.await
.context("could not insert compat access token")?; .context("could not insert compat access token")?;
let token = CompatAccessToken { let token = CompatAccessToken {
@@ -208,9 +223,12 @@ pub async fn compat_logout(
) -> Result<(), anyhow::Error> { ) -> Result<(), anyhow::Error> {
let res = sqlx::query!( let res = sqlx::query!(
r#" r#"
UPDATE compat_access_tokens UPDATE compat_sessions
SET deleted_at = NOW() SET deleted_at = NOW()
WHERE token = $1 AND deleted_at IS NULL FROM compat_access_tokens
WHERE compat_access_tokens.token = $1
AND compat_sessions.id = compat_access_tokens.id
AND compat_sessions.deleted_at IS NULL
"#, "#,
token, token,
) )