runtimes/protocol/identity-management.ts (191 lines of code) (raw):
import {
LSPErrorCodes,
ProgressType,
ProtocolNotificationType,
ProtocolRequestType,
ResponseError,
UpdateCredentialsParams,
} from './lsp'
// Errors
export const AwsErrorCodes = {
E_CANNOT_CREATE_PROFILE: 'E_CANNOT_CREATE_PROFILE',
E_CANNOT_CREATE_SSO_SESSION: 'E_CANNOT_CREATE_SSO_SESSION',
E_CANNOT_OVERWRITE_PROFILE: 'E_CANNOT_OVERWRITE_PROFILE',
E_CANNOT_OVERWRITE_SSO_SESSION: 'E_CANNOT_OVERWRITE_SSO_SESSION',
E_CANNOT_READ_SHARED_CONFIG: 'E_CANNOT_READ_SHARED_CONFIG',
E_CANNOT_READ_SSO_CACHE: 'E_CANNOT_READ_SSO_CACHE',
E_CANNOT_REFRESH_SSO_TOKEN: 'E_CANNOT_REFRESH_SSO_TOKEN',
E_CANNOT_REGISTER_CLIENT: 'E_CANNOT_REGISTER_CLIENT',
E_CANNOT_CREATE_SSO_TOKEN: 'E_CANNOT_CREATE_SSO_TOKEN',
E_CANNOT_WRITE_SHARED_CONFIG: 'E_CANNOT_WRITE_SHARED_CONFIG',
E_CANNOT_WRITE_SSO_CACHE: 'E_CANNOT_WRITE_SSO_CACHE',
E_ENCRYPTION_REQUIRED: 'E_ENCRYPTION_REQUIRED',
E_INVALID_PROFILE: 'E_INVALID_PROFILE',
E_INVALID_SSO_CLIENT: 'E_INVALID_SSO_CLIENT',
E_INVALID_SSO_SESSION: 'E_INVALID_SSO_SESSION',
E_INVALID_SSO_TOKEN: 'E_INVALID_SSO_TOKEN',
E_PROFILE_NOT_FOUND: 'E_PROFILE_NOT_FOUND',
E_RUNTIME_NOT_SUPPORTED: 'E_RUNTIME_NOT_SUPPORTED',
E_SSO_SESSION_NOT_FOUND: 'E_SSO_SESSION_NOT_FOUND',
E_SSO_TOKEN_EXPIRED: 'E_SSO_TOKEN_EXPIRED',
E_SSO_TOKEN_SOURCE_NOT_SUPPORTED: 'E_SSO_TOKEN_SOURCE_NOT_SUPPORTED',
E_TIMEOUT: 'E_TIMEOUT',
E_UNKNOWN: 'E_UNKNOWN',
E_CANCELLED: 'E_CANCELLED',
} as const
export interface AwsResponseErrorData {
awsErrorCode: string
}
export class AwsResponseError extends ResponseError<AwsResponseErrorData> {
constructor(message: string, data: AwsResponseErrorData, code: number = LSPErrorCodes.RequestFailed) {
super(code, message, data)
Object.setPrototypeOf(this, new.target.prototype)
}
}
// listProfiles
export type ProfileKind = 'Unknown' | 'SsoTokenProfile'
export const ProfileKind = {
SsoTokenProfile: 'SsoTokenProfile',
Unknown: 'Unknown',
} as const
// Profile and SsoSession use 'settings' property as namescope for their settings to avoid future
// name conflicts with 'kinds', 'name', and future properties as well as making some setting
// iteration operations easier.
export interface Profile {
kinds: ProfileKind[]
name: string
settings?: {
region?: string
sso_session?: string
}
}
export interface SsoSession {
name: string
settings?: {
sso_start_url?: string
sso_region?: string
sso_registration_scopes?: string[]
}
}
export type ListProfilesParams = {
// Intentionally left blank
}
export interface ListProfilesResult {
profiles: Profile[]
ssoSessions: SsoSession[]
}
// Potential error codes: E_UNKNOWN | E_TIMEOUT | E_RUNTIME_NOT_SUPPORTED | E_CANNOT_READ_SHARED_CONFIG
export const listProfilesRequestType = new ProtocolRequestType<
ListProfilesParams,
ListProfilesResult,
never,
AwsResponseError,
void
>('aws/identity/listProfiles')
// updateProfile
export interface UpdateProfileOptions {
createNonexistentProfile?: boolean
createNonexistentSsoSession?: boolean
updateSharedSsoSession?: boolean
}
export const updateProfileOptionsDefaults = {
createNonexistentProfile: true,
createNonexistentSsoSession: true,
updateSharedSsoSession: false,
} satisfies UpdateProfileOptions
// To change a setting, pass the new value set on it. To delete a setting, set it to null or undefined.
// Settings not provided are ignored, preserving the previous value, if any, in the shared config files.
export interface UpdateProfileParams {
profile: Profile
ssoSession?: SsoSession
options?: UpdateProfileOptions
}
export interface UpdateProfileResult {
// Intentionally left blank
}
// Potential error codes: E_UNKNOWN | E_TIMEOUT | E_RUNTIME_NOT_SUPPORTED | E_CANNOT_READ_SHARED_CONFIG
// E_CANNOT_WRITE_SHARED_CONFIG | E_CANNOT_CREATE_PROFILE | E_CANNOT_OVERWRITE_PROFILE | E_CANNOT_CREATE_SSO_SESSION
// E_CANNOT_OVERWRITE_SSO_SESSION | E_INVALID_PROFILE | E_INVALID_SSO_SESSION
export const updateProfileRequestType = new ProtocolRequestType<
UpdateProfileParams,
UpdateProfileResult,
never,
AwsResponseError,
void
>('aws/identity/updateProfile')
// getSsoToken
export type SsoTokenId = string // Opaque identifier
export type IamIdentityCenterSsoTokenSourceKind = 'IamIdentityCenter'
export type AwsBuilderIdSsoTokenSourceKind = 'AwsBuilderId'
export type SsoTokenSourceKind = IamIdentityCenterSsoTokenSourceKind | AwsBuilderIdSsoTokenSourceKind
export const SsoTokenSourceKind = {
IamIdentityCenter: 'IamIdentityCenter',
AwsBuilderId: 'AwsBuilderId',
} as const
export interface AwsBuilderIdSsoTokenSource {
kind: AwsBuilderIdSsoTokenSourceKind
ssoRegistrationScopes: string[]
}
export interface IamIdentityCenterSsoTokenSource {
kind: IamIdentityCenterSsoTokenSourceKind
profileName: string
}
export type InProgress = 'InProgress'
export type Complete = 'Complete'
export type GetSsoTokenProgressState = InProgress | Complete
export const GetSsoTokenProgressState = {
InProgress: 'InProgress',
Complete: 'Complete',
} as const
export interface GetSsoTokenProgress {
message?: string
state: GetSsoTokenProgressState
}
export const GetSsoTokenProgressType = new ProgressType<GetSsoTokenProgress>()
// Use this to identify the sendProgress/onProgress call from the identity server.
// It indicates that an SSO login is currently in progress.
export const GetSsoTokenProgressToken = 'aws/identity/getSsoToken/progressToken'
export type DeviceCodeAuthorizationFlowKind = 'DeviceCode'
export type PkceAuthorizationFlowKind = 'Pkce'
export type AuthorizationFlowKind = DeviceCodeAuthorizationFlowKind | PkceAuthorizationFlowKind
export const AuthorizationFlowKind = {
DeviceCode: 'DeviceCode',
Pkce: 'Pkce',
} as const
export interface GetSsoTokenOptions {
loginOnInvalidToken?: boolean
authorizationFlow?: AuthorizationFlowKind // Unused if loginOnInvalidToken is false
}
export const getSsoTokenOptionsDefaults = {
loginOnInvalidToken: true,
authorizationFlow: AuthorizationFlowKind.Pkce,
} satisfies GetSsoTokenOptions
export interface GetSsoTokenParams {
source: IamIdentityCenterSsoTokenSource | AwsBuilderIdSsoTokenSource
clientName: string
options?: GetSsoTokenOptions
}
export interface SsoToken {
id: SsoTokenId
accessToken: string // This field is encrypted with JWT like 'update'
// Additional fields captured in token cache file may be added here in the future
}
export interface GetSsoTokenResult {
ssoToken: SsoToken
updateCredentialsParams: UpdateCredentialsParams
}
// Potential error codes: E_UNKNOWN | E_TIMEOUT | E_ENCRYPTION_REQUIRED | E_INVALID_TOKEN
export const getSsoTokenRequestType = new ProtocolRequestType<
GetSsoTokenParams,
GetSsoTokenResult,
never,
AwsResponseError,
void
>('aws/identity/getSsoToken')
// invalidateSsoToken
export interface InvalidateSsoTokenParams {
ssoTokenId: SsoTokenId
}
export interface InvalidateSsoTokenResult {
// Intentionally left blank
}
// Pontential error codes: E_UNKNOWN | E_TIMEOUT | E_CANNOT_READ_SSO_CACHE | E_CANNOT_WRITE_SSO_CACHE | E_INVALID_TOKEN
export const invalidateSsoTokenRequestType = new ProtocolRequestType<
InvalidateSsoTokenParams,
InvalidateSsoTokenResult,
never,
AwsResponseError,
void
>('aws/identity/invalidateSsoToken')
// ssoTokenChanged
export type Expired = 'Expired'
export type Refreshed = 'Refreshed'
export type SsoTokenChangedKind = Refreshed | Expired
export const SsoTokenChangedKind = {
Expired: 'Expired',
Refreshed: 'Refreshed',
} as const
export interface SsoTokenChangedParams {
kind: SsoTokenChangedKind
ssoTokenId: SsoTokenId
}
export const ssoTokenChangedRequestType = new ProtocolNotificationType<SsoTokenChangedParams, void>(
'aws/identity/ssoTokenChanged'
)