@tyravel/auth 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth-manager.d.ts +27 -0
- package/dist/auth-manager.d.ts.map +1 -0
- package/dist/auth-manager.js +102 -0
- package/dist/auth-manager.js.map +1 -0
- package/dist/auth.test.d.ts +2 -0
- package/dist/auth.test.d.ts.map +1 -0
- package/dist/auth.test.js +67 -0
- package/dist/auth.test.js.map +1 -0
- package/dist/authorization-exceptions.d.ts +7 -0
- package/dist/authorization-exceptions.d.ts.map +1 -0
- package/dist/authorization-exceptions.js +13 -0
- package/dist/authorization-exceptions.js.map +1 -0
- package/dist/exceptions.d.ts +7 -0
- package/dist/exceptions.d.ts.map +1 -0
- package/dist/exceptions.js +13 -0
- package/dist/exceptions.js.map +1 -0
- package/dist/gate.d.ts +16 -0
- package/dist/gate.d.ts.map +1 -0
- package/dist/gate.js +66 -0
- package/dist/gate.js.map +1 -0
- package/dist/gate.test.d.ts +2 -0
- package/dist/gate.test.d.ts.map +1 -0
- package/dist/gate.test.js +33 -0
- package/dist/gate.test.js.map +1 -0
- package/dist/hasher.d.ts +5 -0
- package/dist/hasher.d.ts.map +1 -0
- package/dist/hasher.js +28 -0
- package/dist/hasher.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/oauth.d.ts +40 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +178 -0
- package/dist/oauth.js.map +1 -0
- package/dist/oauth.test.d.ts +2 -0
- package/dist/oauth.test.d.ts.map +1 -0
- package/dist/oauth.test.js +17 -0
- package/dist/oauth.test.js.map +1 -0
- package/dist/password-reset-broker.d.ts +20 -0
- package/dist/password-reset-broker.d.ts.map +1 -0
- package/dist/password-reset-broker.js +68 -0
- package/dist/password-reset-broker.js.map +1 -0
- package/dist/personal-access-token-repository.d.ts +14 -0
- package/dist/personal-access-token-repository.d.ts.map +1 -0
- package/dist/personal-access-token-repository.js +55 -0
- package/dist/personal-access-token-repository.js.map +1 -0
- package/dist/policy.d.ts +3 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +3 -0
- package/dist/policy.js.map +1 -0
- package/dist/session-guard.d.ts +26 -0
- package/dist/session-guard.d.ts.map +1 -0
- package/dist/session-guard.js +118 -0
- package/dist/session-guard.js.map +1 -0
- package/dist/session-store.d.ts +18 -0
- package/dist/session-store.d.ts.map +1 -0
- package/dist/session-store.js +69 -0
- package/dist/session-store.js.map +1 -0
- package/dist/session.d.ts +18 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +33 -0
- package/dist/session.js.map +1 -0
- package/dist/token-guard.d.ts +20 -0
- package/dist/token-guard.d.ts.map +1 -0
- package/dist/token-guard.js +51 -0
- package/dist/token-guard.js.map +1 -0
- package/dist/token.test.d.ts +2 -0
- package/dist/token.test.d.ts.map +1 -0
- package/dist/token.test.js +11 -0
- package/dist/token.test.js.map +1 -0
- package/dist/types.d.ts +73 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/user-provider.d.ts +15 -0
- package/dist/user-provider.d.ts.map +1 -0
- package/dist/user-provider.js +30 -0
- package/dist/user-provider.js.map +1 -0
- package/package.json +41 -0
package/dist/oauth.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { QueryBuilder } from '@tyravel/database';
|
|
3
|
+
export class GithubOAuthDriver {
|
|
4
|
+
config;
|
|
5
|
+
name = 'github';
|
|
6
|
+
constructor(config) {
|
|
7
|
+
this.config = config;
|
|
8
|
+
}
|
|
9
|
+
authorizationUrl(state) {
|
|
10
|
+
const params = new URLSearchParams({
|
|
11
|
+
client_id: this.config.clientId,
|
|
12
|
+
redirect_uri: this.config.redirectUri,
|
|
13
|
+
scope: (this.config.scopes ?? ['user:email']).join(' '),
|
|
14
|
+
state,
|
|
15
|
+
});
|
|
16
|
+
return `https://github.com/login/oauth/authorize?${params}`;
|
|
17
|
+
}
|
|
18
|
+
async exchangeCode(code) {
|
|
19
|
+
const tokenRes = await fetch('https://github.com/login/oauth/access_token', {
|
|
20
|
+
method: 'POST',
|
|
21
|
+
headers: {
|
|
22
|
+
accept: 'application/json',
|
|
23
|
+
'content-type': 'application/json',
|
|
24
|
+
},
|
|
25
|
+
body: JSON.stringify({
|
|
26
|
+
client_id: this.config.clientId,
|
|
27
|
+
client_secret: this.config.clientSecret,
|
|
28
|
+
code,
|
|
29
|
+
redirect_uri: this.config.redirectUri,
|
|
30
|
+
}),
|
|
31
|
+
});
|
|
32
|
+
const tokenJson = (await tokenRes.json());
|
|
33
|
+
if (!tokenJson.access_token) {
|
|
34
|
+
throw new Error(tokenJson.error ?? 'OAuth token exchange failed');
|
|
35
|
+
}
|
|
36
|
+
const userRes = await fetch('https://api.github.com/user', {
|
|
37
|
+
headers: {
|
|
38
|
+
authorization: `Bearer ${tokenJson.access_token}`,
|
|
39
|
+
accept: 'application/json',
|
|
40
|
+
'user-agent': 'tyravel-auth',
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
const user = (await userRes.json());
|
|
44
|
+
return {
|
|
45
|
+
id: String(user.id),
|
|
46
|
+
email: user.email ?? null,
|
|
47
|
+
name: user.name ?? user.login ?? null,
|
|
48
|
+
avatar: user.avatar_url ?? null,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export class GoogleOAuthDriver {
|
|
53
|
+
config;
|
|
54
|
+
name = 'google';
|
|
55
|
+
constructor(config) {
|
|
56
|
+
this.config = config;
|
|
57
|
+
}
|
|
58
|
+
authorizationUrl(state) {
|
|
59
|
+
const params = new URLSearchParams({
|
|
60
|
+
client_id: this.config.clientId,
|
|
61
|
+
redirect_uri: this.config.redirectUri,
|
|
62
|
+
response_type: 'code',
|
|
63
|
+
scope: (this.config.scopes ?? ['openid', 'email', 'profile']).join(' '),
|
|
64
|
+
state,
|
|
65
|
+
access_type: 'online',
|
|
66
|
+
});
|
|
67
|
+
return `https://accounts.google.com/o/oauth2/v2/auth?${params}`;
|
|
68
|
+
}
|
|
69
|
+
async exchangeCode(code) {
|
|
70
|
+
const tokenRes = await fetch('https://oauth2.googleapis.com/token', {
|
|
71
|
+
method: 'POST',
|
|
72
|
+
headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
73
|
+
body: new URLSearchParams({
|
|
74
|
+
client_id: this.config.clientId,
|
|
75
|
+
client_secret: this.config.clientSecret,
|
|
76
|
+
code,
|
|
77
|
+
grant_type: 'authorization_code',
|
|
78
|
+
redirect_uri: this.config.redirectUri,
|
|
79
|
+
}),
|
|
80
|
+
});
|
|
81
|
+
const tokenJson = (await tokenRes.json());
|
|
82
|
+
if (!tokenJson.access_token) {
|
|
83
|
+
throw new Error(tokenJson.error ?? 'OAuth token exchange failed');
|
|
84
|
+
}
|
|
85
|
+
const userRes = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', {
|
|
86
|
+
headers: { authorization: `Bearer ${tokenJson.access_token}` },
|
|
87
|
+
});
|
|
88
|
+
const user = (await userRes.json());
|
|
89
|
+
return {
|
|
90
|
+
id: user.id,
|
|
91
|
+
email: user.email ?? null,
|
|
92
|
+
name: user.name ?? null,
|
|
93
|
+
avatar: user.picture ?? null,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
export class OAuthManager {
|
|
98
|
+
connection;
|
|
99
|
+
accountsTable;
|
|
100
|
+
userModel;
|
|
101
|
+
drivers = new Map();
|
|
102
|
+
constructor(providers, connection, accountsTable, userModel) {
|
|
103
|
+
this.connection = connection;
|
|
104
|
+
this.accountsTable = accountsTable;
|
|
105
|
+
this.userModel = userModel;
|
|
106
|
+
for (const [name, config] of Object.entries(providers)) {
|
|
107
|
+
if (name === 'github') {
|
|
108
|
+
this.drivers.set(name, new GithubOAuthDriver(config));
|
|
109
|
+
}
|
|
110
|
+
else if (name === 'google') {
|
|
111
|
+
this.drivers.set(name, new GoogleOAuthDriver(config));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
createState() {
|
|
116
|
+
return randomBytes(24).toString('base64url');
|
|
117
|
+
}
|
|
118
|
+
redirectUrl(provider, state) {
|
|
119
|
+
const driver = this.drivers.get(provider);
|
|
120
|
+
if (!driver) {
|
|
121
|
+
throw new Error(`OAuth provider not configured: ${provider}`);
|
|
122
|
+
}
|
|
123
|
+
return driver.authorizationUrl(state);
|
|
124
|
+
}
|
|
125
|
+
async handleCallback(provider, code) {
|
|
126
|
+
const driver = this.drivers.get(provider);
|
|
127
|
+
if (!driver) {
|
|
128
|
+
throw new Error(`OAuth provider not configured: ${provider}`);
|
|
129
|
+
}
|
|
130
|
+
return driver.exchangeCode(code);
|
|
131
|
+
}
|
|
132
|
+
async findOrCreateUser(provider, profile) {
|
|
133
|
+
const existing = await new QueryBuilder(this.connection, this.accountsTable)
|
|
134
|
+
.where('provider', provider)
|
|
135
|
+
.where('provider_user_id', profile.id)
|
|
136
|
+
.first();
|
|
137
|
+
if (existing) {
|
|
138
|
+
const user = await this.userModel.find(existing.user_id);
|
|
139
|
+
if (user) {
|
|
140
|
+
return user;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const ModelClass = this.userModel;
|
|
144
|
+
let user = null;
|
|
145
|
+
if (profile.email) {
|
|
146
|
+
user = (await ModelClass.query()
|
|
147
|
+
.where('email', profile.email)
|
|
148
|
+
.firstModel());
|
|
149
|
+
}
|
|
150
|
+
if (!user) {
|
|
151
|
+
const now = Math.floor(Date.now() / 1000);
|
|
152
|
+
const inserted = await ModelClass.query().insert({
|
|
153
|
+
name: profile.name ?? 'User',
|
|
154
|
+
email: profile.email ?? `${provider}-${profile.id}@oauth.local`,
|
|
155
|
+
password: randomBytes(32).toString('hex'),
|
|
156
|
+
created_at: now,
|
|
157
|
+
updated_at: now,
|
|
158
|
+
});
|
|
159
|
+
user = (await ModelClass.find(inserted));
|
|
160
|
+
}
|
|
161
|
+
const linked = await new QueryBuilder(this.connection, this.accountsTable)
|
|
162
|
+
.where('provider', provider)
|
|
163
|
+
.where('provider_user_id', profile.id)
|
|
164
|
+
.first();
|
|
165
|
+
if (!linked) {
|
|
166
|
+
await new QueryBuilder(this.connection, this.accountsTable).insert({
|
|
167
|
+
user_id: Number(user.getAuthIdentifier()),
|
|
168
|
+
provider,
|
|
169
|
+
provider_user_id: profile.id,
|
|
170
|
+
email: profile.email,
|
|
171
|
+
avatar: profile.avatar,
|
|
172
|
+
created_at: Math.floor(Date.now() / 1000),
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
return user;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=oauth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.test.d.ts","sourceRoot":"","sources":["../src/oauth.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { GithubOAuthDriver } from './oauth.js';
|
|
3
|
+
describe('OAuth drivers', () => {
|
|
4
|
+
it('builds GitHub authorize URL with state', () => {
|
|
5
|
+
const driver = new GithubOAuthDriver({
|
|
6
|
+
clientId: 'cid',
|
|
7
|
+
clientSecret: 'secret',
|
|
8
|
+
redirectUri: 'http://localhost/callback',
|
|
9
|
+
scopes: ['user:email'],
|
|
10
|
+
});
|
|
11
|
+
const url = new URL(driver.authorizationUrl('state-123'));
|
|
12
|
+
expect(url.hostname).toBe('github.com');
|
|
13
|
+
expect(url.searchParams.get('client_id')).toBe('cid');
|
|
14
|
+
expect(url.searchParams.get('state')).toBe('state-123');
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
//# sourceMappingURL=oauth.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.test.js","sourceRoot":"","sources":["../src/oauth.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC;YACnC,QAAQ,EAAE,KAAK;YACf,YAAY,EAAE,QAAQ;YACtB,WAAW,EAAE,2BAA2B;YACxC,MAAM,EAAE,CAAC,YAAY,CAAC;SACvB,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC;QAC1D,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtD,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { DatabaseConnection } from '@tyravel/database';
|
|
2
|
+
import type { PasswordBrokerConfig } from './types.js';
|
|
3
|
+
import type { UserProvider } from './user-provider.js';
|
|
4
|
+
export declare class PasswordResetBroker {
|
|
5
|
+
private readonly connection;
|
|
6
|
+
private readonly config;
|
|
7
|
+
private readonly provider;
|
|
8
|
+
private readonly hasher;
|
|
9
|
+
constructor(connection: DatabaseConnection, config: PasswordBrokerConfig, provider: UserProvider);
|
|
10
|
+
sendResetLink(email: string): Promise<string>;
|
|
11
|
+
reset(input: {
|
|
12
|
+
email: string;
|
|
13
|
+
token: string;
|
|
14
|
+
password: string;
|
|
15
|
+
}): Promise<void>;
|
|
16
|
+
private tokenValid;
|
|
17
|
+
private hashToken;
|
|
18
|
+
private issueDummyToken;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=password-reset-broker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password-reset-broker.d.ts","sourceRoot":"","sources":["../src/password-reset-broker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAI5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AASvD,qBAAa,mBAAmB;IAI5B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAL3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;gBAGpB,UAAU,EAAE,kBAAkB,EAC9B,MAAM,EAAE,oBAAoB,EAC5B,QAAQ,EAAE,YAAY;IAGnC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAuB7C,KAAK,CAAC,KAAK,EAAE;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BjB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,eAAe;CAGxB"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
2
|
+
import { QueryBuilder } from '@tyravel/database';
|
|
3
|
+
import { Hasher } from './hasher.js';
|
|
4
|
+
import { InvalidResetTokenException } from './authorization-exceptions.js';
|
|
5
|
+
export class PasswordResetBroker {
|
|
6
|
+
connection;
|
|
7
|
+
config;
|
|
8
|
+
provider;
|
|
9
|
+
hasher = new Hasher();
|
|
10
|
+
constructor(connection, config, provider) {
|
|
11
|
+
this.connection = connection;
|
|
12
|
+
this.config = config;
|
|
13
|
+
this.provider = provider;
|
|
14
|
+
}
|
|
15
|
+
async sendResetLink(email) {
|
|
16
|
+
const user = await this.provider.retrieveByCredentials({ email });
|
|
17
|
+
if (!user) {
|
|
18
|
+
return this.issueDummyToken();
|
|
19
|
+
}
|
|
20
|
+
const plainToken = randomBytes(32).toString('hex');
|
|
21
|
+
const hashed = this.hashToken(plainToken);
|
|
22
|
+
const now = Math.floor(Date.now() / 1000);
|
|
23
|
+
await new QueryBuilder(this.connection, this.config.table)
|
|
24
|
+
.where('email', email)
|
|
25
|
+
.delete();
|
|
26
|
+
await new QueryBuilder(this.connection, this.config.table).insert({
|
|
27
|
+
email,
|
|
28
|
+
token: hashed,
|
|
29
|
+
created_at: now,
|
|
30
|
+
});
|
|
31
|
+
return plainToken;
|
|
32
|
+
}
|
|
33
|
+
async reset(input) {
|
|
34
|
+
const row = await new QueryBuilder(this.connection, this.config.table)
|
|
35
|
+
.where('email', input.email)
|
|
36
|
+
.first();
|
|
37
|
+
if (!row || !this.tokenValid(row, input.token)) {
|
|
38
|
+
throw new InvalidResetTokenException();
|
|
39
|
+
}
|
|
40
|
+
const user = await this.provider.retrieveByCredentials({ email: input.email });
|
|
41
|
+
if (!user) {
|
|
42
|
+
throw new InvalidResetTokenException();
|
|
43
|
+
}
|
|
44
|
+
const { Model } = await import('@tyravel/database');
|
|
45
|
+
const ModelClass = user.constructor;
|
|
46
|
+
const passwordHash = this.hasher.make(input.password);
|
|
47
|
+
await ModelClass.query()
|
|
48
|
+
.where('id', user.getAuthIdentifier())
|
|
49
|
+
.update({ password: passwordHash });
|
|
50
|
+
await new QueryBuilder(this.connection, this.config.table)
|
|
51
|
+
.where('email', input.email)
|
|
52
|
+
.delete();
|
|
53
|
+
}
|
|
54
|
+
tokenValid(row, plain) {
|
|
55
|
+
const ageMinutes = (Math.floor(Date.now() / 1000) - row.created_at) / 60;
|
|
56
|
+
if (ageMinutes > this.config.expireMinutes) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return this.hashToken(plain) === row.token;
|
|
60
|
+
}
|
|
61
|
+
hashToken(token) {
|
|
62
|
+
return createHash('sha256').update(token).digest('hex');
|
|
63
|
+
}
|
|
64
|
+
issueDummyToken() {
|
|
65
|
+
return randomBytes(32).toString('hex');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=password-reset-broker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password-reset-broker.js","sourceRoot":"","sources":["../src/password-reset-broker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DatabaseConnection } from '@tyravel/database';
|
|
2
|
+
import type { Authenticatable } from './types.js';
|
|
3
|
+
import type { NewAccessToken } from './types.js';
|
|
4
|
+
export declare class PersonalAccessTokenRepository {
|
|
5
|
+
private readonly connection;
|
|
6
|
+
private readonly table;
|
|
7
|
+
private readonly tokenableType;
|
|
8
|
+
constructor(connection: DatabaseConnection, table: string, tokenableType?: string);
|
|
9
|
+
createToken(user: Authenticatable, name: string, abilities?: string[], expiresAt?: Date): Promise<NewAccessToken>;
|
|
10
|
+
findUserIdByBearerToken(bearer: string, lookupUser: (id: number) => Promise<Authenticatable | null>): Promise<Authenticatable | null>;
|
|
11
|
+
revokeTokensForUser(userId: number): Promise<void>;
|
|
12
|
+
private hashToken;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=personal-access-token-repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"personal-access-token-repository.d.ts","sourceRoot":"","sources":["../src/personal-access-token-repository.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAcjD,qBAAa,6BAA6B;IAEtC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAFb,UAAU,EAAE,kBAAkB,EAC9B,KAAK,EAAE,MAAM,EACb,aAAa,SAAU;IAGpC,WAAW,CACf,IAAI,EAAE,eAAe,EACrB,IAAI,EAAE,MAAM,EACZ,SAAS,GAAE,MAAM,EAAU,EAC3B,SAAS,CAAC,EAAE,IAAI,GACf,OAAO,CAAC,cAAc,CAAC;IAmBpB,uBAAuB,CAC3B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,GAC1D,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAsB5B,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxD,OAAO,CAAC,SAAS;CAGlB"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
2
|
+
import { QueryBuilder } from '@tyravel/database';
|
|
3
|
+
export class PersonalAccessTokenRepository {
|
|
4
|
+
connection;
|
|
5
|
+
table;
|
|
6
|
+
tokenableType;
|
|
7
|
+
constructor(connection, table, tokenableType = 'users') {
|
|
8
|
+
this.connection = connection;
|
|
9
|
+
this.table = table;
|
|
10
|
+
this.tokenableType = tokenableType;
|
|
11
|
+
}
|
|
12
|
+
async createToken(user, name, abilities = ['*'], expiresAt) {
|
|
13
|
+
const plainTextToken = randomBytes(32).toString('hex');
|
|
14
|
+
const hashed = this.hashToken(plainTextToken);
|
|
15
|
+
const now = Math.floor(Date.now() / 1000);
|
|
16
|
+
await new QueryBuilder(this.connection, this.table).insert({
|
|
17
|
+
tokenable_type: this.tokenableType,
|
|
18
|
+
tokenable_id: Number(user.getAuthIdentifier()),
|
|
19
|
+
name,
|
|
20
|
+
token: hashed,
|
|
21
|
+
abilities: JSON.stringify(abilities),
|
|
22
|
+
last_used_at: null,
|
|
23
|
+
expires_at: expiresAt ? Math.floor(expiresAt.getTime() / 1000) : null,
|
|
24
|
+
created_at: now,
|
|
25
|
+
});
|
|
26
|
+
return { plainTextToken, name, abilities };
|
|
27
|
+
}
|
|
28
|
+
async findUserIdByBearerToken(bearer, lookupUser) {
|
|
29
|
+
const hashed = this.hashToken(bearer);
|
|
30
|
+
const row = await new QueryBuilder(this.connection, this.table)
|
|
31
|
+
.where('token', hashed)
|
|
32
|
+
.first();
|
|
33
|
+
if (!row) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
if (row.expires_at !== null && row.expires_at < Math.floor(Date.now() / 1000)) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
const now = Math.floor(Date.now() / 1000);
|
|
40
|
+
await new QueryBuilder(this.connection, this.table)
|
|
41
|
+
.where('id', row.id)
|
|
42
|
+
.update({ last_used_at: now });
|
|
43
|
+
return lookupUser(row.tokenable_id);
|
|
44
|
+
}
|
|
45
|
+
async revokeTokensForUser(userId) {
|
|
46
|
+
await new QueryBuilder(this.connection, this.table)
|
|
47
|
+
.where('tokenable_type', this.tokenableType)
|
|
48
|
+
.where('tokenable_id', userId)
|
|
49
|
+
.delete();
|
|
50
|
+
}
|
|
51
|
+
hashToken(token) {
|
|
52
|
+
return createHash('sha256').update(token).digest('hex');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=personal-access-token-repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"personal-access-token-repository.js","sourceRoot":"","sources":["../src/personal-access-token-repository.ts"],"names":[],"mappings":"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"}
|
package/dist/policy.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA,8BAAsB,MAAM;CAAG"}
|
package/dist/policy.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA,MAAM,OAAgB,MAAM;CAAG"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { TyravelRequest } from '@tyravel/http';
|
|
2
|
+
import type { SessionStore } from './session.js';
|
|
3
|
+
import type { UserProvider } from './user-provider.js';
|
|
4
|
+
import type { Authenticatable, AuthConfig, Guard } from './types.js';
|
|
5
|
+
type WebResponse = globalThis.Response;
|
|
6
|
+
export declare class SessionGuard implements Guard {
|
|
7
|
+
private readonly provider;
|
|
8
|
+
private readonly store;
|
|
9
|
+
private readonly sessionConfig;
|
|
10
|
+
readonly name: string;
|
|
11
|
+
private session?;
|
|
12
|
+
private currentUser;
|
|
13
|
+
private request?;
|
|
14
|
+
constructor(name: string, provider: UserProvider, store: SessionStore, sessionConfig: AuthConfig['session']);
|
|
15
|
+
setRequest(request: TyravelRequest): void;
|
|
16
|
+
startSession(): Promise<void>;
|
|
17
|
+
persistSession(response: WebResponse): Promise<WebResponse>;
|
|
18
|
+
user(): Authenticatable | null;
|
|
19
|
+
id(): string | number | null;
|
|
20
|
+
check(): boolean;
|
|
21
|
+
attempt(credentials: Record<string, string>): Promise<boolean>;
|
|
22
|
+
login(user: Authenticatable): Promise<void>;
|
|
23
|
+
logout(): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=session-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-guard.d.ts","sourceRoot":"","sources":["../src/session-guard.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAErE,KAAK,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC;AAMvC,qBAAa,YAAa,YAAW,KAAK;IAQtC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAThC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,OAAO,CAAC,CAAU;IAC1B,OAAO,CAAC,WAAW,CAAgC;IACnD,OAAO,CAAC,OAAO,CAAC,CAAiB;gBAG/B,IAAI,EAAE,MAAM,EACK,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,YAAY,EACnB,aAAa,EAAE,UAAU,CAAC,SAAS,CAAC;IAKvD,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAInC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB7B,cAAc,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAmBjE,IAAI,IAAI,eAAe,GAAG,IAAI;IAI9B,EAAE,IAAI,MAAM,GAAG,MAAM,GAAG,IAAI;IAI5B,KAAK,IAAI,OAAO;IAIV,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAe9D,KAAK,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAY3C,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAS9B"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { InvalidCredentialsException } from './exceptions.js';
|
|
3
|
+
import { Session } from './session.js';
|
|
4
|
+
function sessionKey(guard) {
|
|
5
|
+
return `auth.${guard}.user_id`;
|
|
6
|
+
}
|
|
7
|
+
export class SessionGuard {
|
|
8
|
+
provider;
|
|
9
|
+
store;
|
|
10
|
+
sessionConfig;
|
|
11
|
+
name;
|
|
12
|
+
session;
|
|
13
|
+
currentUser = null;
|
|
14
|
+
request;
|
|
15
|
+
constructor(name, provider, store, sessionConfig) {
|
|
16
|
+
this.provider = provider;
|
|
17
|
+
this.store = store;
|
|
18
|
+
this.sessionConfig = sessionConfig;
|
|
19
|
+
this.name = name;
|
|
20
|
+
}
|
|
21
|
+
setRequest(request) {
|
|
22
|
+
this.request = request;
|
|
23
|
+
}
|
|
24
|
+
async startSession() {
|
|
25
|
+
if (!this.request) {
|
|
26
|
+
throw new Error('Request not set on guard');
|
|
27
|
+
}
|
|
28
|
+
const cookieName = this.sessionConfig.cookie;
|
|
29
|
+
const existingId = readCookie(this.request, cookieName);
|
|
30
|
+
const id = existingId ?? randomBytes(32).toString('base64url');
|
|
31
|
+
const data = await this.store.read(id);
|
|
32
|
+
this.session = new Session(id, data);
|
|
33
|
+
this.request.session = this.session;
|
|
34
|
+
const userId = this.session.get(sessionKey(this.name));
|
|
35
|
+
if (userId !== undefined) {
|
|
36
|
+
this.currentUser = await this.provider.retrieveById(userId);
|
|
37
|
+
this.request.user = this.currentUser;
|
|
38
|
+
}
|
|
39
|
+
else if (!this.request.user) {
|
|
40
|
+
this.request.user = null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async persistSession(response) {
|
|
44
|
+
if (!this.session) {
|
|
45
|
+
return response;
|
|
46
|
+
}
|
|
47
|
+
if (this.session.isDirty()) {
|
|
48
|
+
await this.store.write(this.session.id, this.session.all(), this.sessionConfig.lifetimeMinutes);
|
|
49
|
+
this.session.markClean();
|
|
50
|
+
}
|
|
51
|
+
const cookieName = this.sessionConfig.cookie;
|
|
52
|
+
const maxAge = this.sessionConfig.lifetimeMinutes * 60;
|
|
53
|
+
return withCookie(response, cookieName, this.session.id, maxAge);
|
|
54
|
+
}
|
|
55
|
+
user() {
|
|
56
|
+
return this.currentUser;
|
|
57
|
+
}
|
|
58
|
+
id() {
|
|
59
|
+
return this.currentUser?.getAuthIdentifier() ?? null;
|
|
60
|
+
}
|
|
61
|
+
check() {
|
|
62
|
+
return this.currentUser !== null;
|
|
63
|
+
}
|
|
64
|
+
async attempt(credentials) {
|
|
65
|
+
const user = await this.provider.retrieveByCredentials(credentials);
|
|
66
|
+
if (!user) {
|
|
67
|
+
throw new InvalidCredentialsException();
|
|
68
|
+
}
|
|
69
|
+
const valid = await this.provider.validateCredentials(user, credentials);
|
|
70
|
+
if (!valid) {
|
|
71
|
+
throw new InvalidCredentialsException();
|
|
72
|
+
}
|
|
73
|
+
await this.login(user);
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
async login(user) {
|
|
77
|
+
this.currentUser = user;
|
|
78
|
+
if (!this.session) {
|
|
79
|
+
throw new Error('Session not started');
|
|
80
|
+
}
|
|
81
|
+
this.session.put(sessionKey(this.name), user.getAuthIdentifier());
|
|
82
|
+
if (this.request) {
|
|
83
|
+
this.request.user = user;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async logout() {
|
|
87
|
+
this.currentUser = null;
|
|
88
|
+
if (this.session) {
|
|
89
|
+
this.session.forget(sessionKey(this.name));
|
|
90
|
+
}
|
|
91
|
+
if (this.request) {
|
|
92
|
+
this.request.user = null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function readCookie(request, name) {
|
|
97
|
+
const header = request.header('cookie');
|
|
98
|
+
if (!header) {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
for (const part of header.split(';')) {
|
|
102
|
+
const [key, ...rest] = part.trim().split('=');
|
|
103
|
+
if (key === name) {
|
|
104
|
+
return decodeURIComponent(rest.join('='));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
function withCookie(response, name, value, maxAge) {
|
|
110
|
+
const headers = new Headers(response.headers);
|
|
111
|
+
headers.append('set-cookie', `${name}=${encodeURIComponent(value)}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${maxAge}`);
|
|
112
|
+
return new globalThis.Response(response.body, {
|
|
113
|
+
status: response.status,
|
|
114
|
+
statusText: response.statusText,
|
|
115
|
+
headers,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=session-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-guard.js","sourceRoot":"","sources":["../src/session-guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { DatabaseConnection } from '@tyravel/database';
|
|
2
|
+
import type { SessionStore } from './session.js';
|
|
3
|
+
export declare class DatabaseSessionStore implements SessionStore {
|
|
4
|
+
private readonly connection;
|
|
5
|
+
private readonly table;
|
|
6
|
+
constructor(connection: DatabaseConnection, table?: string);
|
|
7
|
+
read(id: string): Promise<Record<string, unknown>>;
|
|
8
|
+
write(id: string, data: Record<string, unknown>, lifetimeMinutes: number): Promise<void>;
|
|
9
|
+
destroy(id: string): Promise<void>;
|
|
10
|
+
pruneExpired(lifetimeMinutes: number): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export declare class MemorySessionStore implements SessionStore {
|
|
13
|
+
private readonly sessions;
|
|
14
|
+
read(id: string): Promise<Record<string, unknown>>;
|
|
15
|
+
write(id: string, data: Record<string, unknown>, _lifetimeMinutes: number): Promise<void>;
|
|
16
|
+
destroy(id: string): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=session-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-store.d.ts","sourceRoot":"","sources":["../src/session-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AASjD,qBAAa,oBAAqB,YAAW,YAAY;IAErD,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,KAAK;gBADL,UAAU,EAAE,kBAAkB,EAC9B,KAAK,SAAa;IAG/B,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAgBlD,KAAK,CACT,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC;IA2BV,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlC,YAAY,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAM3D;AAED,qBAAa,kBAAmB,YAAW,YAAY;IACrD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8C;IAEjE,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAIlD,KAAK,CACT,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,IAAI,CAAC;IAIV,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGzC"}
|