SQL Server Adapter
Resources
Setup
Installation
npm install @auth/sqlserver-adapter mssql
Environment Variables
DATABASE_HOST=
DATABASE_NAME=
DATABASE_USER=
DATABASE_PASSWORD=
Configuration
./auth.ts
import NextAuth from "next-auth"
import SqlServerAdapter from "@auth/sqlserver-adapter"
import sql from "mssql"
const client = new sql.ConnectionPool({
server: process.env.DATABASE_HOST,
database: process.env.DATABASE_NAME,
user: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
pool: {
max: 10,
min: 0,
idleTimeoutMillis: 30000,
},
options: {
encrypt: true,
trustServerCertificate: true,
},
})
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: SqlServerAdapter(pool),
providers: [],
})
Schema
The SQL schema for the tables used by this adapter is as follows. Learn more about the models at our doc page on Database Models.
-- USERS table
IF NOT EXISTS
(SELECT 1
FROM sys.objects
WHERE object_id = OBJECT_ID(N'[users]')
AND type IN ( N'U' )
)
BEGIN
CREATE TABLE [users]
(
[id] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [df_users_id] DEFAULT NEWSEQUENTIALID(),
[name] NVARCHAR(100) NULL,
[email] NVARCHAR(100) NOT NULL,
[emailVerified] DATETIME2 NULL,
[image] VARCHAR(8000) NULL
);
END
GO
-- PK constraint and index
IF NOT EXISTS
(SELECT 1
FROM sys.indexes
WHERE object_id = OBJECT_ID(N'[users]')
AND name = N'pk_users'
)
BEGIN
ALTER TABLE [users]
ADD CONSTRAINT [pk_users]
PRIMARY KEY CLUSTERED (
[id] ASC
)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY];
END
GO
-- ACCOUNTS table
IF NOT EXISTS
(SELECT 1
FROM sys.objects
WHERE object_id = OBJECT_ID(N'[accounts]')
AND type IN ( N'U' )
)
BEGIN
CREATE TABLE [accounts]
(
[id] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [df_accounts_id] DEFAULT NEWSEQUENTIALID(),
[userId] UNIQUEIDENTIFIER NOT NULL,
[type] NVARCHAR(100) NOT NULL,
[provider] NVARCHAR(100) NOT NULL,
[providerAccountId] NVARCHAR(100) NOT NULL,
[refresh_token] VARCHAR(8000) NULL,
[access_token] VARCHAR(8000) NULL,
[expires_at] INT NULL,
[token_type] NVARCHAR(100) NULL,
[scope] NVARCHAR(100) NULL,
[id_token] VARCHAR(8000) NULL,
[session_state] NVARCHAR(100) NULL
);
END
GO
-- PK constraint and index
IF NOT EXISTS
(SELECT 1
FROM sys.indexes
WHERE object_id = OBJECT_ID(N'[accounts]')
AND name = N'pk_accounts'
)
BEGIN
ALTER TABLE [accounts]
ADD CONSTRAINT [pk_accounts]
PRIMARY KEY CLUSTERED (
[id] ASC
)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY];
END
GO
-- FK index
IF NOT EXISTS
(SELECT 1
FROM sys.indexes
WHERE object_id = OBJECT_ID(N'[accounts]')
AND name = N'ix_accounts_users'
)
BEGIN
CREATE INDEX [ix_accounts_users] ON [accounts] (userId);
END
GO
-- FK constraint
IF NOT EXISTS
(SELECT 1
FROM sys.foreign_keys
WHERE parent_object_id = OBJECT_ID(N'[accounts]')
AND name = N'fk_accounts_users'
)
BEGIN
ALTER TABLE [accounts] WITH CHECK
ADD CONSTRAINT [fk_accounts_users]
FOREIGN KEY ([userId])
REFERENCES [users] ([id]) ON DELETE CASCADE;
END
GO
-- SESSION table
IF NOT EXISTS
(SELECT 1
FROM sys.objects
WHERE object_id = OBJECT_ID(N'[sessions]')
AND type IN ( N'U' )
)
BEGIN
CREATE TABLE [sessions]
(
[id] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [df_sessions_id] DEFAULT NEWSEQUENTIALID(),
[expires] DATETIME2 NOT NULL,
[userId] UNIQUEIDENTIFIER NOT NULL,
[sessionToken] VARCHAR(8000) NULL
);
END
GO
-- PK index and constraint
IF NOT EXISTS
(SELECT 1
FROM sys.indexes
WHERE object_id = OBJECT_ID(N'[sessions]')
AND name = N'pk_sessions'
)
BEGIN
ALTER TABLE [sessions]
ADD CONSTRAINT [pk_sessions]
PRIMARY KEY CLUSTERED (
[id] ASC
)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY];
END
GO
-- FK index
IF NOT EXISTS
(SELECT 1
FROM sys.indexes
WHERE object_id = OBJECT_ID(N'[sessions]')
AND name = N'ix_sessions_users'
)
BEGIN
CREATE INDEX [ix_sessions_users] ON [sessions] (userId)
END
GO
-- FK constraint
IF NOT EXISTS
(SELECT 1
FROM sys.foreign_keys
WHERE parent_object_id = OBJECT_ID(N'[sessions]')
AND name = N'fk_sessions_users'
)
BEGIN
ALTER TABLE [sessions] WITH CHECK
ADD CONSTRAINT [fk_sessions_users]
FOREIGN KEY ([userId])
REFERENCES [users] ([id]) ON DELETE CASCADE;
END
GO
-- VERIFICATION_TOKENS table
IF NOT EXISTS
(SELECT 1
FROM sys.objects
WHERE object_id = OBJECT_ID(N'[verification_tokens]')
AND type IN ( N'U' )
)
BEGIN
CREATE TABLE [verification_tokens]
(
[identifier] NVARCHAR(100) NOT NULL,
[token] VARCHAR(700) NOT NULL,
[expires] DATETIME2 NOT NULL
);
END
GO
-- PK index and constraint
IF NOT EXISTS
(SELECT 1
FROM sys.indexes
WHERE object_id = OBJECT_ID(N'[verification_tokens]')
AND name = N'pk_verification_tokens'
)
BEGIN
ALTER TABLE [verification_tokens]
ADD CONSTRAINT [pk_verification_tokens]
PRIMARY KEY CLUSTERED (
[identifier] ASC,
[token] ASC
)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY];
END
GO
CREATE OR ALTER PROCEDURE dbo.create_user
@name NVARCHAR(100),
@email NVARCHAR(100),
@emailVerified DATETIME2,
@image VARCHAR(8000)
AS
BEGIN
DECLARE @new_id TABLE
(
id UNIQUEIDENTIFIER
);
INSERT INTO [users]
(
[name],
[email],
[emailVerified],
[image]
)
OUTPUT INSERTED.id
INTO @new_id
VALUES
(@name, @email, @emailVerified, @image);
-- only return IUser fields
SELECT
[id],
[name],
[email],
[emailVerified],
[image]
FROM [users]
WHERE [id] =
(SELECT TOP 1 id FROM @new_id);
END
GO
CREATE OR ALTER PROCEDURE dbo.get_user_by_id @id UNIQUEIDENTIFIER
AS
BEGIN
SELECT
*
FROM [users]
WHERE [id] = @id;
END
GO
CREATE OR ALTER PROCEDURE dbo.get_user_by_email @email NVARCHAR(100)
AS
BEGIN
SELECT
*
FROM [users]
WHERE [email] = @email;
END
GO
CREATE OR ALTER PROCEDURE dbo.get_user_by_account
@providerAccountId NVARCHAR(100),
@provider NVARCHAR(100)
AS
BEGIN
SELECT
u.*
FROM [users] u
LEFT JOIN [accounts] a
ON a.[userId] = u.[id]
WHERE a.[providerAccountId] = @providerAccountId
AND a.[provider] = @provider;
END
GO
CREATE OR ALTER PROCEDURE dbo.update_user
@id UNIQUEIDENTIFIER,
@name NVARCHAR(100) = NULL,
@email NVARCHAR(100) = NULL,
@emailVerified DATETIME2 = NULL,
@image VARCHAR(8000) = NULL
AS
BEGIN
UPDATE [users]
SET
[name] = COALESCE(@name, [name]),
[email] = COALESCE(@email, [email]),
[emailVerified] = COALESCE(@emailVerified, [emailVerified]),
[image] = COALESCE(@image, [image])
WHERE [id] = @id;
SELECT
[id],
[name],
[email],
[emailVerified],
[image]
FROM [users]
WHERE [id] = @id;
END
GO
CREATE OR ALTER PROCEDURE dbo.link_account_to_user
@provider NVARCHAR(100),
@type NVARCHAR(100),
@providerAccountId NVARCHAR(100),
@refresh_token VARCHAR(8000),
@token_type NVARCHAR(100),
@scope NVARCHAR(100),
@expires_at INT,
@access_token VARCHAR(8000),
@id_token VARCHAR(8000),
@session_state NVARCHAR(100),
@userId UNIQUEIDENTIFIER
AS
BEGIN
DECLARE @new_id TABLE
(
id UNIQUEIDENTIFIER
);
INSERT INTO [accounts]
(
[provider],
[type],
[providerAccountId],
[refresh_token],
[token_type],
[scope],
[expires_at],
[access_token],
[id_token],
[session_state],
[userId]
)
OUTPUT INSERTED.id
INTO @new_id
VALUES
(@provider, @type, @providerAccountId, @refresh_token, @token_type, @scope,
@expires_at, @access_token, @id_token, @session_state, @userId);
SELECT
[id],
[userId],
[type],
[provider],
[providerAccountId],
[refresh_token],
[access_token],
[expires_at],
[token_type],
[scope],
[id_token],
[session_state]
FROM [accounts]
WHERE [id] =
(SELECT TOP 1 id FROM @new_id);
END
GO
CREATE OR ALTER PROCEDURE dbo.create_session_for_user
@sessionToken VARCHAR(100),
@userId UNIQUEIDENTIFIER,
@expires DATETIME2
AS
BEGIN
DECLARE @new_id TABLE
(
id UNIQUEIDENTIFIER
);
INSERT INTO [sessions]
(
[sessionToken],
[userId],
[expires]
)
OUTPUT INSERTED.id
INTO @new_id
VALUES
(@sessionToken, @userId, @expires);
SELECT
[sessionToken],
[userId],
[expires]
FROM [sessions]
WHERE [id] =
(SELECT TOP 1 id FROM @new_id);
END
GO
CREATE OR ALTER PROCEDURE dbo.get_session_and_user @sessionToken VARCHAR(100)
AS
BEGIN
DECLARE @userId UNIQUEIDENTIFIER;
SELECT
*
FROM [sessions]
WHERE [sessionToken] = @sessionToken;
SELECT @userId = [userId]
FROM [sessions]
WHERE [sessionToken] = @sessionToken;
EXEC dbo.get_user_by_id @userId;
END
GO
CREATE OR ALTER PROCEDURE dbo.update_session
@sessionToken VARCHAR(100),
@userId UNIQUEIDENTIFIER,
@expires DATETIME2
AS
BEGIN
UPDATE [sessions]
SET
[userId] = @userId,
[expires] = @expires
WHERE [sessionToken] = @sessionToken;
END
GO
CREATE OR ALTER PROCEDURE dbo.delete_session
@sessionToken VARCHAR(100)
AS
BEGIN
DELETE FROM [sessions]
WHERE [sessionToken] = @sessionToken;
END
GO
CREATE OR ALTER PROCEDURE dbo.delete_user
@userId UNIQUEIDENTIFIER
AS
BEGIN
DELETE FROM [users]
WHERE [id] = @userId;
END
GO
CREATE OR ALTER PROCEDURE dbo.create_verification_token
@identifier NVARCHAR(100),
@token VARCHAR(8000),
@expires DATETIME2
AS
BEGIN
INSERT INTO [verification_tokens]
(
[identifier],
[token],
[expires]
)
VALUES
(@identifier, @token, @expires);
SELECT
[identifier],
[token],
[expires]
FROM [verification_tokens]
WHERE [identifier] = @identifier AND [token] = @token;
END
GO
CREATE OR ALTER PROCEDURE dbo.use_verification_token
@identifier NVARCHAR(100),
@token VARCHAR(8000)
AS
BEGIN
DELETE FROM [verification_tokens]
OUTPUT DELETED.identifier, DELETED.token, DELETED.expires
WHERE [identifier] = @identifier AND [token] = @token;
END
GO
CREATE OR ALTER PROCEDURE dbo.unlink_account
@providerAccountId NVARCHAR(100),
@provider NVARCHAR(100)
AS
BEGIN
DELETE FROM [accounts]
WHERE [providerAccountId] = @providerAccountId AND [provider] = @provider;
END
GO