-
-
Notifications
You must be signed in to change notification settings - Fork 252
feat: allow partial revokes via wallet_revokeSession
#6668
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
Changes from all commits
8269d22
4f141de
53b569f
c89ddcd
9a87173
9c518af
9a55a2d
dbdc6e6
96faa58
739a339
a57d978
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
jiexi marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,41 +1,113 @@ | ||
import { Caip25EndowmentPermissionName } from '@metamask/chain-agnostic-permission'; | ||
import { | ||
Caip25CaveatMutators, | ||
Caip25CaveatType, | ||
Caip25EndowmentPermissionName, | ||
getCaipAccountIdsFromCaip25CaveatValue, | ||
} from '@metamask/chain-agnostic-permission'; | ||
import type { | ||
JsonRpcEngineNextCallback, | ||
JsonRpcEngineEndCallback, | ||
} from '@metamask/json-rpc-engine'; | ||
import { | ||
CaveatMutatorOperation, | ||
PermissionDoesNotExistError, | ||
UnrecognizedSubjectError, | ||
} from '@metamask/permission-controller'; | ||
import { rpcErrors } from '@metamask/rpc-errors'; | ||
import type { JsonRpcSuccess, JsonRpcRequest } from '@metamask/utils'; | ||
|
||
import type { WalletRevokeSessionHooks } from './types'; | ||
|
||
/** | ||
* Revokes specific session scopes from an existing caveat. | ||
* Fully revokes permission if no accounts remain permitted after iterating through scopes. | ||
* | ||
* @param scopes - Array of scope strings to remove from the caveat. | ||
* @param hooks - The hooks object. | ||
* @param hooks.revokePermissionForOrigin - The hook for revoking a permission for an origin function. | ||
* @param hooks.updateCaveat - The hook used to conditionally update the caveat rather than fully revoke the permission. | ||
* @param hooks.getCaveatForOrigin - The hook to fetch an existing caveat for the origin of the request. | ||
*/ | ||
function partialRevokePermissions( | ||
scopes: string[], | ||
hooks: WalletRevokeSessionHooks, | ||
) { | ||
let updatedCaveatValue = hooks.getCaveatForOrigin( | ||
Caip25EndowmentPermissionName, | ||
Caip25CaveatType, | ||
).value; | ||
|
||
for (const scopeString of scopes) { | ||
const result = Caip25CaveatMutators[Caip25CaveatType].removeScope( | ||
updatedCaveatValue, | ||
scopeString, | ||
); | ||
|
||
// If operation is a Noop, it means a scope was passed that was not present in the permission, so we proceed with the loop | ||
if (result.operation === CaveatMutatorOperation.Noop) { | ||
continue; | ||
} | ||
|
||
updatedCaveatValue = result?.value ?? { | ||
requiredScopes: {}, | ||
optionalScopes: {}, | ||
sessionProperties: {}, | ||
isMultichainOrigin: true, | ||
}; | ||
} | ||
ffmcgee725 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
const caipAccountIds = | ||
getCaipAccountIdsFromCaip25CaveatValue(updatedCaveatValue); | ||
|
||
// We fully revoke permission if no accounts are left after scope removal loop. | ||
if (!caipAccountIds.length) { | ||
hooks.revokePermissionForOrigin(Caip25EndowmentPermissionName); | ||
} else { | ||
hooks.updateCaveat( | ||
Caip25EndowmentPermissionName, | ||
Caip25CaveatType, | ||
updatedCaveatValue, | ||
); | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Permission Revocation Errors and Null HandlingThe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
/** | ||
* Handler for the `wallet_revokeSession` RPC method as specified by [CAIP-285](https://chainagnostic.org/CAIPs/caip-285). | ||
* The implementation below deviates from the linked spec in that it ignores the `sessionId` param | ||
* and instead revokes the singular session for the origin if available. Additionally, | ||
* the handler also does not return an error if there is currently no active session and instead | ||
* returns true which is the same result returned if an active session was actually revoked. | ||
* | ||
* @param _request - The JSON-RPC request object. Unused. | ||
* @param request - The JSON-RPC request object. Unused. | ||
* @param response - The JSON-RPC response object. | ||
* @param _next - The next middleware function. Unused. | ||
* @param end - The end callback function. | ||
* @param hooks - The hooks object. | ||
* @param hooks.revokePermissionForOrigin - The hook for revoking a permission for an origin function. | ||
* @param hooks.updateCaveat - The hook used to conditionally update the caveat rather than fully revoke the permission. | ||
* @param hooks.getCaveatForOrigin - The hook to fetch an existing caveat for the origin of the request. | ||
* @returns Nothing. | ||
*/ | ||
async function walletRevokeSessionHandler( | ||
_request: JsonRpcRequest & { origin: string }, | ||
request: JsonRpcRequest & { | ||
origin: string; | ||
params: { scopes?: string[] }; | ||
}, | ||
response: JsonRpcSuccess, | ||
_next: JsonRpcEngineNextCallback, | ||
end: JsonRpcEngineEndCallback, | ||
hooks: { | ||
revokePermissionForOrigin: (permissionName: string) => void; | ||
}, | ||
hooks: WalletRevokeSessionHooks, | ||
) { | ||
const { | ||
params: { scopes }, | ||
} = request; | ||
|
||
try { | ||
hooks.revokePermissionForOrigin(Caip25EndowmentPermissionName); | ||
if (scopes?.length) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if we pass an empty array of scopes, what should happen? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. right, that's what happens right now, but is that what we want? If i say "hey, please remove the following specific scopes from my permission, nothing", should it remove everything? Idk. anyway not worth blocking on and probably not important right now |
||
partialRevokePermissions(scopes, hooks); | ||
} else { | ||
hooks.revokePermissionForOrigin(Caip25EndowmentPermissionName); | ||
} | ||
} catch (err) { | ||
if ( | ||
!(err instanceof UnrecognizedSubjectError) && | ||
|
@@ -54,5 +126,7 @@ export const walletRevokeSession = { | |
implementation: walletRevokeSessionHandler, | ||
hookNames: { | ||
revokePermissionForOrigin: true, | ||
updateCaveat: true, | ||
getCaveatForOrigin: true, | ||
}, | ||
}; |
Uh oh!
There was an error while loading. Please reload this page.