CREATE TABLE IF NOT EXISTS oidc_authentications ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, provider VARCHAR(50) NOT NULL, provider_issuer VARCHAR(255) NOT NULL, trust_anchor VARCHAR(255) NOT NULL, state VARCHAR(128) NOT NULL, nonce VARCHAR(128) NOT NULL, pkce_verifier VARCHAR(255) NOT NULL, code_challenge VARCHAR(255) NOT NULL, frontend_redirect_uri VARCHAR(500) NULL, authorization_endpoint VARCHAR(500) NULL, token_endpoint VARCHAR(500) NULL, userinfo_endpoint VARCHAR(500) NULL, federation_resolve_endpoint VARCHAR(500) NULL, request_object_jwt TEXT NULL, provider_metadata JSON NULL, trust_chain_json JSON NULL, status ENUM( 'CREATED', 'AUTHORIZATION_REDIRECT_READY', 'CALLBACK_RECEIVED', 'TOKENS_RECEIVED', 'USERINFO_RECEIVED', 'AUTHENTICATED', 'FAILED' ) NOT NULL DEFAULT 'CREATED', error_code VARCHAR(100) NULL, error_message TEXT NULL, authenticated_user_id BIGINT UNSIGNED NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, completed_at DATETIME NULL, UNIQUE KEY oidc_authentications_state_unique (state), KEY oidc_authentications_status_idx (status), KEY oidc_authentications_provider_idx (provider), CONSTRAINT oidc_authentications_user_fk FOREIGN KEY (authenticated_user_id) REFERENCES users(id) ); CREATE TABLE IF NOT EXISTS oidc_authentication_tokens ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, authentication_id BIGINT UNSIGNED NOT NULL, authorization_code TEXT NULL, access_token TEXT NULL, id_token TEXT NULL, refresh_token TEXT NULL, token_type VARCHAR(50) NULL, scope VARCHAR(255) NULL, expires_in_seconds INT NULL, access_token_expires_at DATETIME NULL, refresh_token_expires_at DATETIME NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, CONSTRAINT oidc_auth_tokens_auth_fk FOREIGN KEY (authentication_id) REFERENCES oidc_authentications(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS oidc_federation_cache ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, document_type ENUM( 'ENTITY_CONFIGURATION', 'ENTITY_STATEMENT', 'RESOLVE_RESPONSE', 'JWKS' ) NOT NULL, issuer VARCHAR(255) NOT NULL, subject VARCHAR(255) NULL, fetch_url VARCHAR(500) NOT NULL, cache_key BINARY(32) GENERATED ALWAYS AS ( UNHEX( SHA2( JSON_ARRAY(document_type, issuer, subject, fetch_url), 256 ) ) ) STORED, payload_json JSON NOT NULL, expires_at DATETIME NOT NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY oidc_federation_cache_unique (cache_key), KEY oidc_federation_cache_expires_idx (expires_at) ); CREATE TABLE IF NOT EXISTS user_external_identities ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, user_id BIGINT UNSIGNED NOT NULL, provider VARCHAR(50) NOT NULL, issuer VARCHAR(255) NOT NULL, subject VARCHAR(255) NOT NULL, fiscal_code VARCHAR(16) NULL, raw_claims JSON NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY user_external_identities_provider_subject_unique ( provider, issuer, subject ), KEY user_external_identities_user_idx (user_id), KEY user_external_identities_fiscal_code_idx (fiscal_code), CONSTRAINT user_external_identities_user_fk FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE );