Skip to content

Commit 8b7cfed

Browse files
committed
create OAuthClientRepository + client utils
1 parent a759a6d commit 8b7cfed

File tree

2 files changed

+112
-0
lines changed

2 files changed

+112
-0
lines changed
+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { GrantIdentifier, OAuthClient, OAuthClientRepository } from '@jmondi/oauth2-server'
2+
import { getClient, clientExists, clientHasGrantType } from 'src/oauth2/client/utils'
3+
4+
class SendOAuthClientRepository implements OAuthClientRepository {
5+
/**
6+
* Gets client from client id
7+
* @param {string} identifier - client identifier (`client_id`)
8+
* @returns {Promise<OAuthClient>} - OAuthClient object
9+
*/
10+
async getByIdentifier(identifier: string): Promise<OAuthClient> {
11+
return await getClient(identifier)
12+
}
13+
14+
/**
15+
* Checks if the client is valid. The client is valid if:
16+
* - The client exists
17+
* - AND the client is authorized for the requested grant type
18+
* @param {GrantIdentifier} grantType - requested grant type
19+
* @param {OAuthClient} client - client
20+
* @param {string | undefined} clientSecret - client secret (not required as we are using PKCE) @see {https://tsoauth2server.com/docs/grants/authorization_code}
21+
* @returns {Promise<boolean>}
22+
*/
23+
async isClientValid(
24+
grantType: GrantIdentifier,
25+
client: OAuthClient,
26+
clientSecret?: string
27+
): Promise<boolean> {
28+
const doesClientExist = await clientExists(client.id)
29+
if (!doesClientExist) {
30+
return false
31+
}
32+
const clientHasAuthorizationGrantType: boolean = await clientHasGrantType(client.id, grantType)
33+
if (!clientHasAuthorizationGrantType) {
34+
return false
35+
}
36+
return true
37+
}
38+
}
+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import type { GrantIdentifier, OAuthClient, OAuthScope } from '@jmondi/oauth2-server'
2+
import { supabaseAdmin } from 'app/utils/supabase/admin'
3+
import debug from 'debug'
4+
5+
const logger = debug.log
6+
7+
export const getClient = async (clientId: string): Promise<OAuthClient> => {
8+
try {
9+
const { data, error } = await supabaseAdmin
10+
.from('oauth2_clients')
11+
.select('*')
12+
.eq('client_id', clientId)
13+
.single()
14+
if (error) {
15+
logger(error)
16+
throw error
17+
}
18+
return {
19+
id: data.client_id,
20+
name: data.client_name,
21+
redirectUris: [data.redirect_uri],
22+
allowedGrants: await getClientGrants(clientId),
23+
scopes: await getClientScopes(clientId),
24+
}
25+
} catch (error) {
26+
logger(`Error retrieving client from client id: [${clientId}]. ${error})`)
27+
throw error
28+
}
29+
}
30+
31+
export const clientExists = async (clientId: string): Promise<boolean> => {
32+
const { data, error } = await supabaseAdmin
33+
.from('oauth2_clients')
34+
.select('*')
35+
.eq('client_id', clientId)
36+
.single()
37+
if (error) {
38+
logger(`Unable to determine whether client exists. clientId: [${clientId}]. ${error}`)
39+
return false
40+
}
41+
return !!data
42+
}
43+
44+
export const clientHasGrantType = async (
45+
clientId: string,
46+
grantType: GrantIdentifier
47+
): Promise<boolean> => {
48+
const clientGrants: GrantIdentifier[] = await getClientGrants(clientId)
49+
return clientGrants.includes(grantType)
50+
}
51+
52+
export const getClientGrants = async (clientId: string): Promise<GrantIdentifier[]> => {
53+
const { data, error } = await supabaseAdmin
54+
.from('oauth2_client_authorization_grant_types')
55+
.select('grant_type')
56+
.eq('client_id', clientId)
57+
if (error) {
58+
logger(error)
59+
throw error
60+
}
61+
return data.map((grant) => grant.grant_type) as GrantIdentifier[]
62+
}
63+
64+
export const getClientScopes = async (clientId: string): Promise<OAuthScope[]> => {
65+
const { data, error } = await supabaseAdmin
66+
.from('oauth2_client_scopes')
67+
.select('name')
68+
.eq('client_id', clientId)
69+
if (error) {
70+
logger(error)
71+
return []
72+
}
73+
return data
74+
}

0 commit comments

Comments
 (0)