Authentication
v5
Using clientId
and clientSecret
:
import {Client} from 'plainid-pdp-sdk/v5'
const options = <ClientConfigInterface>{
url: 'https://demo.plainid.cloud',
clientId: 'P6POYCA8QY5', clientSecret: 'XRp8OXVugWlnDZjP8', authorizerId: 'APA9G5HV7WXN9C'
}
const client: ClientInterface = new Client(options)
v3
Using
clientId
and clientSecret
import {Client} from 'plainid-pdp-sdk/v3'
const config = <ClientConfigInterface>{
url: 'https://demo.plainid.cloud',
clientId: 'P6POYCA8QY5', clientSecret: 'XRp8OXVugWlnDZjP8', authorizerId: 'APA9G5HV7WXN9C'
}
const client = new Client(config)
Using JWT
:
If included in the JWT
payload, the values for clientSecret
and entityId
are optional for this scenario and will be used from there.
import {Client} from 'plainid-pdp-sdk/v3'
const config = <ClientConfigInterface>{
url: 'https://demo.plainid.cloud',
clientId: 'P6POYCA8QY5', authorizerId: 'APA9G5HV7WXN9C'
}
const client = new Client(config)
const options = <AccessDecisionOptionsInterface>{
headers: {
'Authorization': 'Bearer J.W.T'
}
}
const response: ResolutionResponse = await client.resolutionDecision(options).evaluate(payload)
Interfaces
interface ClientConfigInterface {
url: string // PDP url
clientId: string // client id of needed scope
clientSecret?: string // client secret of needed scope
authorizerId: string // authorizer id
}
interface ClientInterface {
getConfig(): ClientConfigInterface;
resolutionDecision(options: ResolutionDecisionOptionsInterface): ResolutionDecisionInterface;
accessDecision(options: AccessDecisionOptionsInterface): AccessDecisionInterface;
}
Access Decision Request (v5)
Important
The path in the following Access Decision payload example is an absolute path that begins with a /. For more information, see Managing API Mappers.
import {Client} from 'plainid-pdp-sdk/v5'
const payload = <AccessDecisionPayloadInterface>{
url: 'https://example.com/full/path?param1=value11¶m1=value12¶m2=value2#some_chapter',
method: 'POST',
headers: { 'header-name': 'header value' },
body: { some: 'data' },
meta: { runtimeFineTune: { includeIdentity: 'true' } }
}
const config = <AccessDecisionOptionsInterface>{
maxAttempts: 2,
delay: 100,
headers: {'some-header': 'some value'},
}
const accessDecision: AccessDecisionInterface = client.accessDecision(config)
const response: AccessDecisionResponseInterface = await accessDecision.evaluate(payload)
Interfaces
interface AccessDecisionPayloadInterface {
url: string // HTTP authorizing request url (required)
method?: string // HTTP request method: POST, GET, PUT, PATCH, DELETE, ...
headers: Record<string, string | string[]> // HTTP request headers
body?: any // HTTP request body
meta?: Record<string, any> // Additional parameters
// Inside `meta` can be used the attribute `runtimeFineTune: Record<string, string>` - Any request attribute understandable by PDP (Runtime)
}
interface AccessDecisionOptionsInterface {
maxAttempts?: number // Maximum number of attempts to retry the request. Default: `1`.
delay?: number // Delay between retries in milliseconds. Default: `0`.
schema: 'http' | 'https' // PDP request schema. Default: `https`.
headers?: Record<string, string> // Additional headers for PDP commucication.
}
interface AccessDecisionResponseInterface {
statusCode: number // http response status code
headers: Record<string, string> // http response headers
body: string // http raw response body
access: boolean | null // acess decision
}
interface AccessDecisionInterface {
getClient(): ClientInterface;
getOptions(): AccessDecisionOptionsInterface;
evaluate(payload: AccessDecisionPayloadInterface): Promise<AccessDecisionResponseInterface>;
}
Resolution Decision Request (v3)
import {Client, AccessDecisionPayloadInterface, ResolutionResponse} from 'plainid-pdp-sdk/v3'
const payload = <AccessDecisionPayloadInterface> {
entityId: 'john.doe@gmail.com',
entityTypeId: 'User',
remoteIp: '1.2.2.1',
includeAssetAttributes: true,
}
const options = <AccessDecisionOptionsInterface>{
maxAttempts: 3,
schema: 'http',
delay: 100,
headers: {
'x-custom-header': 'custom value'
},
resolutionConfig: {
resolutionAttributeProjectId: 'projectid',
resolutionAttributeDataset: 'dataset',
resolutionAttributeTable: 'table',
resolutionAttributeColumn: 'column',
}
}
const response: ResolutionResponse = await client.resolutionDecision(options).evaluate(payload)
Interfaces
interface ResolutionDecisionOptionsInterface {
maxAttempts?: number // Maximum number of attempts to retry the request. Default: `1`.
schema: 'http' | 'https' // PDP request schema. Default: `https`.
delay?: number // Delay between retries in milliseconds. Default: `0`.
headers?: Record<string, string> // Additional headers for PDP commucication.
resolutionConfig?: ResolutionConfigInterface // Resolution config to be used with parsing the PDP response
}
interface ResolutionConfigInterface {
resolutionAttributeProjectId?: string
resolutionAttributeDataset?: string
resolutionAttributeTable?: string
resolutionAttributeColumn?: string
resolutionAttributeMaskAs?: string
resolutionAttributeMaskFilter?: string
resolutionMaskingResourceTypeName?: string
}
interface ResolutionDecisionResponseInterface {
statusCode: string // http status code of the response
headers: Map<string, string> // http headers of the response
body: string // http raw body of the response
resolution: Resolution | null // parsed PDP restrictions and helpers
}
interface Resolution {
getConfig(): Record<string, any>
getAllRestrictions(): Map<string, Restrictions>
getResourceRestrictions(fullResourceName: string): Restrictions
getAllTables(): Set<string>
isAssetMasked(fullResourceName: string, assetName: string): boolean
isAssetAllowed(fullResourceName: string, assetName: string): boolean
existAsset(fullResourceName: string, assetName: string): boolean
existAllowedAssets(fullResourceName: string): boolean
}
interface Restrictions {
FULL_CONDITION_FIELD_NAME: boolean
FIELD_APOSTROPHES: [string, string]
isEmpty(): boolean
mergeWith(restrictions: Restrictions | undefined): Restrictions
addAllowedConditionSql(condition: string): Restrictions
addDeniedConditionSql(condition: string): Restrictions
getConditionSql(): string // (('Country' LIKE '%United%') AND ('balance' < 1000))
getConditionFields(): Set<RestrictionsConditionField>
getIsAccessEmpty(): boolean
setIsAccessEmpty(isAccessEmpty: boolean): this
addAsset(asset: RestrictionsAsset): Restrictions
getAssets(): Map<String, RestrictionsAsset>
getAsset(assetName: string): Optional<RestrictionsAsset>
}
interface RestrictionsConditionField {
name: string // field name, ex: "balance"
type: string // field type, ex: "NUMERIC", "STRING"
}
interface RestrictionsAsset {
fullResourceName: string // full resource name, ex: "dbName.tableName"
name: string // column name, ex: "balance"
maskAs: string // mask for the column, ex: "<censored>"
}
All conditions in one SQL where clause
Restrictions.FULL_CONDITION_FIELD_NAME = true
Restrictions.FIELD_APOSTROPHES = ['', '']
const response = await client.resolutionDecision(options).evaluate(payload)
const allRestrictions = response.resolution.getAllRestrictions()
const whereClause = Array.from(allRestrictions.values()).map(restriction => restriction.getConditionSql()).join(' AND ')
console.log(whereClause) // ((mydb.members.Country LIKE '%United%') AND (mydb.accounts.balance < 1000))
Error handling
Access Decision response (v5)
try {
const response = await client.resolutionDecision(options).evaluate(payload)
} catch (err) {
console.error(err.message) // Example: "Error: getaddrinfo ENOTFOUND api.example.com"
}
Interfaces
interface SdkError {
id: string // unique id of the error
code: string // error code
name: string // code name
message: string // message
args?: Record<string, string> // additional arguments
}
Resolution Decision response (v3)
try {
const response = await client.resolutionDecision(options).evaluate(payload)
} catch (err) {
console.error(err.message) // Example: "Error: getaddrinfo ENOTFOUND api.example.com"
}
Troubleshooting
Error: self-signed certificate in the certificate chain
You can fix this issue using NODE_TLS_REJECT_UNAUTHORIZED=0
in the terminal, or insert the following line within the JS file:
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0;
Note
This is a flag which helps avoid a rejection of an unauthorized (self-signed) certification. It is not recommended to use in a production environment.