-
Notifications
You must be signed in to change notification settings - Fork 4
/
password.ts
81 lines (71 loc) · 2.67 KB
/
password.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import {
AbstractGrant,
GrantInterface,
GrantOptions,
GrantServices,
} from "./grant.ts";
import { InvalidGrantError, InvalidRequestError } from "../errors.ts";
import { Scope as DefaultScope, ScopeInterface } from "../models/scope.ts";
import { UserServiceInterface } from "../services/user.ts";
import { OAuth2Request } from "../context.ts";
import { ClientInterface } from "../models/client.ts";
import { Token } from "../models/token.ts";
export interface PasswordGrantServices<
Client extends ClientInterface,
User,
Scope extends ScopeInterface,
> extends GrantServices<Client, User, Scope> {
userService: UserServiceInterface<User>;
}
export interface PasswordGrantOptions<
Client extends ClientInterface,
User,
Scope extends ScopeInterface,
> extends GrantOptions<Client, User, Scope> {
services: PasswordGrantServices<Client, User, Scope>;
}
export interface PasswordGrantInterface<
Client extends ClientInterface,
User,
Scope extends ScopeInterface,
> extends GrantInterface<Client, User, Scope> {
services: PasswordGrantServices<Client, User, Scope>;
}
/**
* The resource owner password credentials grant type.
* https://datatracker.ietf.org/doc/html/rfc6749.html#section-4.3
* Usage of this grant type is not recommended.
* https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-2.4
*/
export class PasswordGrant<
Client extends ClientInterface,
User,
Scope extends ScopeInterface = DefaultScope,
> extends AbstractGrant<Client, User, Scope>
implements PasswordGrantInterface<Client, User, Scope> {
declare services: PasswordGrantServices<Client, User, Scope>;
constructor(options: PasswordGrantOptions<Client, User, Scope>) {
super(options);
}
async token(
request: OAuth2Request<Client, User, Scope>,
client: Client,
): Promise<Token<Client, User, Scope>> {
const body: URLSearchParams = await request.body;
const scopeText: string | null = body.get("scope");
let scope: Scope | null | undefined = this.parseScope(scopeText);
const username: string | null = body.get("username");
if (!username) throw new InvalidRequestError("username parameter required");
const password: string | null = body.get("password");
if (!password) throw new InvalidRequestError("password parameter required");
const { tokenService, userService } = this.services;
const user: User | void = await userService.getAuthenticated(
username,
password,
);
if (!user) throw new InvalidGrantError("user authentication failed");
scope = await this.acceptedScope(client, user, scope);
const token = await this.generateToken(client, user, scope);
return await tokenService.save(token);
}
}