Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ego-token-utils): defines API to support token verification #19

Merged
merged 1 commit into from
Jul 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 68 additions & 48 deletions src/ego-token-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,26 +52,26 @@ type PermissionScopeObj = {
* checks if a string is a proper permission
* @param str
*/
export const isPermission = (str: any): str is keyof typeof PERMISSIONS =>
const isPermission = (str: any): str is keyof typeof PERMISSIONS =>
Object.values(PERMISSIONS).includes(str)

/**
* wrapper for jwt-decode that provides static Ego typing
* @param egoJwt
*/
export const decodeToken = (egoJwt: string): EgoJwtData => jwtDecode(egoJwt)
const decodeToken = (egoPublicKey: string) => (egoJwt: string): EgoJwtData => jwtDecode(egoJwt)

/**
* checks if a given jwt is valid and has not expired.
* currently does not validate against Ego signature
* @param egoJwt
*/
export const isValidJwt = (egoJwt?: string) => {
const isValidJwt = (egoPublicKey: string) => (egoJwt?: string) => {
try {
if (!egoJwt) {
return false
} else {
const { exp } = decodeToken(egoJwt)
const { exp } = decodeToken(egoPublicKey)(egoJwt)
return exp * 1000 > Date.now()
}
} catch (err) {
Expand All @@ -83,9 +83,9 @@ export const isValidJwt = (egoJwt?: string) => {
* check if a given jwt has dcc access
* @param egoJwt
*/
export const isDccMember = (egoJwt: string) => {
const isDccMember = (egoPublicKey: string) => (egoJwt: string) => {
try {
const data = decodeToken(egoJwt)
const data = decodeToken(egoPublicKey)(egoJwt)
const permissions = data.context.user.permissions
return permissions.some(p => p.includes(DCC_PREFIX))
} catch (err) {
Expand All @@ -97,9 +97,9 @@ export const isDccMember = (egoJwt: string) => {
* check if a given jwt has rdpc access
* @param egoJwt
*/
export const isRdpcMember = (egoJwt: string) => {
const isRdpcMember = (egoPublicKey: string) => (egoJwt: string) => {
try {
const data = decodeToken(egoJwt)
const data = decodeToken(egoPublicKey)(egoJwt)
const permissions = data.context.user.permissions
const rdpcPermissions = permissions.filter(p => {
const policy = p.split('.')[0]
Expand All @@ -119,7 +119,7 @@ export const isRdpcMember = (egoJwt: string) => {
* takes a scope string and returns an object for interpretation
* @param scope should be of the format `<policy>.<permission>`
*/
export const parseScope = (scope: string): PermissionScopeObj => {
const parseScope = (scope: string): PermissionScopeObj => {
const permission = scope.split('.')[1]
if (isPermission(permission)) {
return {
Expand All @@ -135,7 +135,7 @@ export const parseScope = (scope: string): PermissionScopeObj => {
* takes an PermissionScopeObj and returns a scope string in the format `<policy>.<permission>`
* @param scopeObj
*/
export const serializeScope = (scopeObj: PermissionScopeObj): string => {
const serializeScope = (scopeObj: PermissionScopeObj): string => {
if (isPermission(scopeObj.permission)) {
return `${scopeObj.policy}.${scopeObj.permission}`
} else {
Expand All @@ -148,8 +148,10 @@ export const serializeScope = (scopeObj: PermissionScopeObj): string => {
* does not return entries that are given `.DENY`
* @param egoJwt
*/
export const getReadableProgramScopes = (egoJwt: string): PermissionScopeObj[] => {
const data = decodeToken(egoJwt)
const getReadableProgramScopes = (egoPublicKey: string) => (
egoJwt: string
): PermissionScopeObj[] => {
const data = decodeToken(egoPublicKey)(egoJwt)
const permissions = data.context.user.permissions
const programPermissions = permissions.filter(p => {
const policy = p.split('.')[0]
Expand All @@ -170,8 +172,10 @@ export const getReadableProgramScopes = (egoJwt: string): PermissionScopeObj[] =
* does not return entries that are given `.DENY`
* @param egoJwt
*/
export const getWriteableProgramScopes = (egoJwt: string): PermissionScopeObj[] => {
const data = decodeToken(egoJwt)
const getWriteableProgramScopes = (egoPublicKey: string) => (
egoJwt: string
): PermissionScopeObj[] => {
const data = decodeToken(egoPublicKey)(egoJwt)
const permissions = data.context.user.permissions
const programPermissions = permissions.filter(p => {
const policy = p.split('.')[0]
Expand All @@ -192,37 +196,47 @@ export const getWriteableProgramScopes = (egoJwt: string): PermissionScopeObj[]
* in the provided token
* @param egoJwt
*/
export const getReadableProgramShortNames = (egoJwt: string): string[] => {
return getReadableProgramScopes(egoJwt).map(({ policy }) => policy.replace(PROGRAM_PREFIX, ''))
const getReadableProgramShortNames = (egoPublicKey: string) => (egoJwt: string): string[] => {
return getReadableProgramScopes(egoPublicKey)(egoJwt).map(({ policy }) =>
policy.replace(PROGRAM_PREFIX, '')
)
}

/**
* get an array of program short names where the user has been given at least `.READ` permission
* in the provided token
* @param egoJwt
*/
export const getWriteableProgramShortNames = (egoJwt: string): string[] => {
return getWriteableProgramScopes(egoJwt).map(({ policy }) => policy.replace(PROGRAM_PREFIX, ''))
const getWriteableProgramShortNames = (egoPublicKey: string) => (egoJwt: string): string[] => {
return getWriteableProgramScopes(egoPublicKey)(egoJwt).map(({ policy }) =>
policy.replace(PROGRAM_PREFIX, '')
)
}

/**
* check if a given JWT can read program with given id
* @param args
*/
export const canReadProgram = (args: { egoJwt: string; programId: string }): boolean => {
const authorizedProgramScopes = getReadableProgramScopes(args.egoJwt)
const canReadProgram = (egoPublicKey: string) => (args: {
egoJwt: string
programId: string
}): boolean => {
const authorizedProgramScopes = getReadableProgramScopes(egoPublicKey)(args.egoJwt)
const programIds = authorizedProgramScopes.map(({ policy }) => policy.replace(PROGRAM_PREFIX, ''))
return isDccMember(args.egoJwt) || programIds.some(id => id === args.programId)
return isDccMember(egoPublicKey)(args.egoJwt) || programIds.some(id => id === args.programId)
}

/**
* check if a given JWT can write program with given id
* @param args
*/
export const canWriteProgram = (args: { egoJwt: string; programId: string }): boolean => {
const authorizedProgramScopes = getReadableProgramScopes(args.egoJwt)
const canWriteProgram = (egoPublicKey: string) => (args: {
egoJwt: string
programId: string
}): boolean => {
const authorizedProgramScopes = getReadableProgramScopes(egoPublicKey)(args.egoJwt)
return (
isDccMember(args.egoJwt) ||
isDccMember(egoPublicKey)(args.egoJwt) ||
authorizedProgramScopes.some(({ policy, permission }) => {
const programId = policy.replace(PROGRAM_PREFIX, '')
return (
Expand All @@ -236,40 +250,46 @@ export const canWriteProgram = (args: { egoJwt: string; programId: string }): bo
* checks if a given token can read any program at all
* @param egoJwt the ego token
*/
export const canReadSomeProgram = (egoJwt: string) => {
return isDccMember(egoJwt) || !!getReadableProgramScopes(egoJwt).length
const canReadSomeProgram = (egoPublicKey: string) => (egoJwt: string) => {
return (
isDccMember(egoPublicKey)(egoJwt) || !!getReadableProgramScopes(egoPublicKey)(egoJwt).length
)
}

/**
* checks if a given token can write to any program at all
* @param egoJwt the ego token
*/
export const canWriteSomeProgram = (egoJwt: string) => {
return isDccMember(egoJwt) || !!getWriteableProgramScopes(egoJwt).length
const canWriteSomeProgram = (egoPublicKey: string) => (egoJwt: string) => {
return (
isDccMember(egoPublicKey)(egoJwt) || !!getWriteableProgramScopes(egoPublicKey)(egoJwt).length
)
}

/**
* check if a given JWT has admin access to program with given id
* @param args
*/
export const isProgramAdmin = (args: { egoJwt: string; programId: string }): boolean =>
canWriteProgram(args)
const isProgramAdmin = (egoPublicKey: string) => (args: {
egoJwt: string
programId: string
}): boolean => canWriteProgram(egoPublicKey)(args)

export default {
isPermission,
decodeToken,
isValidJwt,
isDccMember,
isRdpcMember,
parseScope,
serializeScope,
getReadableProgramScopes,
getWriteableProgramScopes,
canReadProgram,
canWriteProgram,
isProgramAdmin,
canReadSomeProgram,
canWriteSomeProgram,
getReadableProgramShortNames,
getWriteableProgramShortNames
}
export default (egoPublicKey: string) => ({
serializeScope: serializeScope,
parseScope: parseScope,
isPermission: isPermission,
decodeToken: decodeToken(egoPublicKey),
isValidJwt: isValidJwt(egoPublicKey),
isDccMember: isDccMember(egoPublicKey),
isRdpcMember: isRdpcMember(egoPublicKey),
getReadableProgramScopes: getReadableProgramScopes(egoPublicKey),
getWriteableProgramScopes: getWriteableProgramScopes(egoPublicKey),
canReadProgram: canReadProgram(egoPublicKey),
canWriteProgram: canWriteProgram(egoPublicKey),
isProgramAdmin: isProgramAdmin(egoPublicKey),
canReadSomeProgram: canReadSomeProgram(egoPublicKey),
canWriteSomeProgram: canWriteSomeProgram(egoPublicKey),
getReadableProgramShortNames: getReadableProgramShortNames(egoPublicKey),
getWriteableProgramShortNames: getWriteableProgramShortNames(egoPublicKey)
})
Loading