-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
create OAuthClientRepository + client utils
- Loading branch information
Showing
3 changed files
with
119 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import type { GrantIdentifier, OAuthClient, OAuthClientRepository } from '@jmondi/oauth2-server' | ||
import { OAuthClientUtils } from 'src/oauth2/utils' | ||
|
||
class SendOAuthClientRepository implements OAuthClientRepository { | ||
/** | ||
* Gets client from client id | ||
* @param {string} identifier - client identifier (`client_id`) | ||
* @returns {Promise<OAuthClient>} - OAuthClient object | ||
*/ | ||
async getByIdentifier(identifier: string): Promise<OAuthClient> { | ||
return await OAuthClientUtils.getClient(identifier) | ||
} | ||
|
||
/** | ||
* Checks if the client is valid. The client is valid if: | ||
* - The client exists | ||
* - AND the client is authorized for the requested grant type | ||
* @param {GrantIdentifier} grantType - requested grant type | ||
* @param {OAuthClient} client - client | ||
* @param {string | undefined} clientSecret - client secret (not required as we are using PKCE) @see {https://tsoauth2server.com/docs/grants/authorization_code} | ||
* @returns {Promise<boolean>} | ||
*/ | ||
async isClientValid( | ||
grantType: GrantIdentifier, | ||
client: OAuthClient, | ||
clientSecret?: string | ||
): Promise<boolean> { | ||
const clientExists: boolean = await OAuthClientUtils.clientExists(client.id) | ||
if (!clientExists) { | ||
return false | ||
} | ||
const clientHasAuthorizationGrantType: boolean = await OAuthClientUtils.clientHasGrantType( | ||
client.id, | ||
grantType | ||
) | ||
if (!clientHasAuthorizationGrantType) { | ||
return false | ||
} | ||
return true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export interface OAuthScope { | ||
name: string | ||
[key: string]: string | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import type { GrantIdentifier, OAuthClient } from '@jmondi/oauth2-server' | ||
import { supabaseAdmin } from 'app/utils/supabase/admin' | ||
import debug from 'debug' | ||
import type { OAuthScope } from 'src/oauth2/types' | ||
|
||
const logger = debug.log | ||
|
||
export const getClient = async (clientId: string): Promise<OAuthClient> => { | ||
try { | ||
const { data, error } = await supabaseAdmin | ||
.from('oauth2_clients') | ||
.select('*') | ||
.eq('client_id', clientId) | ||
.single() | ||
if (error) { | ||
logger(error) | ||
throw error | ||
} | ||
return { | ||
id: data.client_id, | ||
name: data.client_name, | ||
redirectUris: [data.redirect_uri], | ||
allowedGrants: await getClientGrants(clientId), | ||
scopes: await getClientScopes(clientId), | ||
} | ||
} catch (error) { | ||
logger(`Error retrieving client from client id: [${clientId}]. ${error})`) | ||
throw error | ||
} | ||
} | ||
export const clientExists = async (clientId: string): Promise<boolean> => { | ||
const { data, error } = await supabaseAdmin | ||
.from('oauth2_clients') | ||
.select('*') | ||
.eq('client_id', clientId) | ||
.single() | ||
if (error) { | ||
logger(`Unable to determine whether client exists. clientId: [${clientId}]. ${error}`) | ||
return false | ||
} | ||
return !!data | ||
} | ||
|
||
export const clientHasGrantType = async ( | ||
clientId: string, | ||
grantType: GrantIdentifier | ||
): Promise<boolean> => { | ||
const clientGrants: GrantIdentifier[] = await getClientGrants(clientId) | ||
return clientGrants.includes(grantType) | ||
} | ||
|
||
export const getClientGrants = async (clientId: string): Promise<GrantIdentifier[]> => { | ||
const { data, error } = await supabaseAdmin | ||
.from('oauth2_client_authorization_grant_types') | ||
.select('grant_type') | ||
.eq('client_id', clientId) | ||
if (error) { | ||
logger(error) | ||
throw error | ||
} | ||
return data.map((grant) => grant.grant_type) as GrantIdentifier[] | ||
} | ||
|
||
export const getClientScopes = async (clientId: string): Promise<OAuthScope[]> => { | ||
const { data, error } = await supabaseAdmin | ||
.from('oauth2_client_scopes') | ||
.select('*') | ||
.eq('client_id', clientId) | ||
if (error) { | ||
logger(error) | ||
return [] | ||
} | ||
return data | ||
} |