Announcing the Saviynt Knowledge Exchange unifying the Saviynt forums, documentation, training,
and more in a single search tool across platforms. Read the announcement here.

Duo account creation issue

GauravJain
Regular Contributor
Regular Contributor

Hi All,

Getting 40103 error while creating accounts in Duo using REST connector. Following is the configuration for 

connectionJSON

{
"authentications": {
"acctAuth": {
"authType": "BasicWithHmac",
"url": "https://.duosecurity.com/admin/v1/admins",
"httpMethod": "GET",
"properties": {
"IKEY": "as received from app team",
"SKEY": "as received from app team"
},
"authError": [
"InvalidAuthenticationToken",
"AuthenticationFailed",
"Authentication_MissingOrMalformed",
"Authentication_ExpiredToken"
],
"errorPath": "code",
"maxRefreshTryCount": 5,
"tokenResponsePath": "access_token",
"tokenType": "Basic",
"accessToken": "Basic {base64 encoded value of "IKEY:SKEY"}"
}
}
}

Note: assuming the password signature is managed internally by Saviynt in Hmac format as per Duo api documentation

CreateAccountJson

{
"accountIdPath": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? 'call1.message.response.admin_id' :'call1.message.response.user_id'}",
"dateFormat": "ddd, DD MMM YYYY HH:mm:ss ZZ",
"responseColsToPropsMap": {
"accountsStatus": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? '#CONST#Active~#~char' : 'call1.message.status~#~char'}",
"displayName": "call1.message.response.realname~#~char",
"name": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser'))?'call1.message.response.email~#~char' : 'call1.message.response.username~#~char'}",
"accountType": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? '#CONST#AdminUser~#~char' :'#CONST#EndUser~#~char'}",
"accountRole": "call1.message.response.role~#~char"
},
"call": [
{
"name": "call1",
"connection": "acctAuth",
"basicUrl": "https://.duosecurity.com",
"hostUrl": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? '/admin/v1/admins' : '/admin/v1/users'}",
"url": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ?'https://.duosecurity.com/admin/v1/admins' : 'https://.duosecurity.com/admin/v1/users'}",
"httpMethod": "POST",
"httpParams": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? '{\"name\": \"${user.displayname}\", \"realname\": \"${user.displayname}\", \"email\": \"${user.email}\", \"status\": \"active\"}' : '{\"username\": \"${user.username}\", \"realname\": \"${user.displayname}\", \"email\": \"${user.email}\", \"status\": \"active\"}'}"
},
{
"name": "call2",
"connection": "acctAuth",
"basicUrl": "https://.duosecurity.com",
"hostUrl": "/admin/v1/users/enroll",
"url": "https://.duosecurity.com/admin/v1/users/enroll",
"httpMethod": "POST",
"httpParams": "{\"email\": \"${user.email}\", \"username\": \"${user.username}\"}",
"successResponses": {
"statusCode": [
200,
400
]
}
}
]
}

here, "call1" is failing as of now. once it starts working then only i think it will go for "call2".

Error message

Got Webservice API Response: [headers:[Server: Duo/1.0, Date: Tue, 20 Feb 2024 05:59:33 GMT, Content-Type: application/json, Content-Length: 86, Connection: keep-alive], responseText:{"code": 40103, "message": "Invalid signature in request credentials", "stat": "FAIL"}, cookies:[], statusCode:401]

Please let me know if you require any further information on this.

Regards

Gaurav

16 REPLIES 16

sudeshjaiswal
Saviynt Employee
Saviynt Employee

Hello @GauravJain,

Did you tried it in the postman, Is it working fine.
As the error indicates the issue is with the connection itself, and currently we are not doing the "Test Connections" at the connection level. Would request you to validate the connections json once again.
https://docs.saviyntcloud.com/bundle/Duo-v23x/page/Content/About-this-Guide.htm#access_to_saviynt_su... 


Thanks.

If you find the above response useful, Kindly Mark it as "Accept As Solution".

Hi @sudeshjaiswal Yes, the create user api is working fine in postman. i have created 2 users from postman already. only after this i have setup Saviynt connectionJson and createAccountJson configuration.

Yes, i have verified the connection details and they look ok as i am using the same credentials in postman also. the error 40103 we are getting is because of the timestamp issue (Duo api status What are Duo's API responses and error messages?) which is managed by Saviynt internally while triggering duo's create user api.

Please let me know in case you require any further information on this.

sudeshjaiswal
Saviynt Employee
Saviynt Employee

Hello @GauravJain,

Looks like  your connection json does not have the correct message for expired token.
Please refer the below connection json : User the below connection json replace it with the credentials.

 

{
  "authentications": {
    "acctAuth": {
      "authType": "BasicWithHmac",
      "url": "####",
      "httpMethod": "POST",
      "properties": {
        "IKEY": "####",
        "SKEY": "####"
      },
      "authError": [
        "InvalidAuthenticationToken",
        "AuthenticationFailed",
        "Authentication_MissingOrMalformed",
        "Authentication_ExpiredToken",
        "Invalid signature in request credentials"
      ],
      "errorPath": "message",
      "retryFailureStatusCode": [
        401
      ],
      "maxRefreshTryCount": 5,
      "tokenResponsePath": "access_token",
      "tokenType": "Basic",
      "accessToken": "Basic xyz"
    }
  }
}

 

CreateAccountJson.

 

{
  "accountIdPath": "call1.message.response.user_id",
  "dateFormat": "yyyy-MM-dd'T'HH:mm:ssXXX",
  "responseColsToPropsMap": {
    "accountsStatus": "call1.message.status~#~char",
    "displayName": "call1.message.response.username~#~char",
    "accountType": "#CONST#EndUser~#~char",
    "accountRole": "call1.message.response.role~#~char"
  },
  "call": [
    {
      "name": "call1",
      "connection": "acctAuth",
      "basicUrl": "api.duosecurity.com",
      "hostUrl": "/admin/v1/users",
      "url": "https://api.duosecurity.com/admin/v1/users",
      "httpMethod": "POST",
      "httpParams": "{\"username\": \"${user.username}\", \"realname\": \"${user.username}\", \"email\": \"${user.email}\", \"status\": \"active\"}"
    }
	,
    {
      "name": "call2",
      "connection": "acctAuth",
	  "basicUrl": "api.duosecurity.com",
	  "hostUrl": "/admin/v1/users/enroll",
      "url": "https://api.duosecurity.com/admin/v1/users/enroll",
      "httpMethod": "POST",
      "httpParams": "{\"email\": \"${user.email}\", \"username\": \"${user.username}\"}",
      "successResponses": 
        {
          "statusCode": [200,400]
        }
    }
  ]
}

 


Please use the above json.

Thanks.

If you find the above response useful, Kindly Mark it as "Accept As Solution".

Hi @sudeshjaiswal thanks for sharing required configuration. I was able to create accounts (Account Type = EndUser) using "CreateAccountJson" configuration where you have fixed the list of httpParams (call1) for Duo "EndUser" type accounts. The only issue i see in logs is 

"Exception in restProvisioningService-updateAccFromProvMetadata try: org.codehaus.groovy.runtime.metaclass.MissingPropertyExceptionNoStack: No such property: accountType for class: com.saviynt.ecm.identitywarehouse.domain.Accounts"

Please guide on above error.

Secondly, to create "AdminUser" accounts i made the configuration dynamic as shown below but its giving me this error in provisioning:

"message":{"code":40002,"message":"Invalid email address: \"${user.email}\".","message_detail":"email","stat":"FAIL"},"statusCode":400,"description":null,"status":"Failed"}"

but if i only change the httpParams configuration to one you have shared (for EndUser type) in the dynamic configuration then it starts working. So not sure what's the difference between your configuration and the dynamic one mentioned below. Need your assistance here

{
"accountIdPath": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? 'call1.message.response.admin_id' :'call1.message.response.user_id'}",
"dateFormat": "yyyy-MM-dd'T'HH:mm:ssXXX",
"responseColsToPropsMap": {
"accountsStatus": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? '#CONST#Active~#~char' : 'call1.message.status~#~char'}",
"displayName": "call1.message.response.realname~#~char",
"name": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser'))?'call1.message.response.email~#~char' : 'call1.message.response.username~#~char'}",
"accountType": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? '#CONST#AdminUser~#~char' :'#CONST#EndUser~#~char'}",
"accountRole": "call1.message.response.role~#~char"
},
"call": [
{
"name": "call1",
"connection": "acctAuth",
"basicUrl": "api.duosecurity.com",
"hostUrl": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? '/admin/v1/admins' : '/admin/v1/users'}",
"url": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ?'https://api.duosecurity.com/admin/v1/admins' : 'https://api.duosecurity.com/admin/v1/users'}",
"httpMethod": "POST",
"httpParams": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? '{\"name\": \"${user.displayname}\", \"email\": \"${user.email}\", \"status\": \"active\"}' : '{\"username\": \"${user.username}\", \"realname\": \"${user.displayname}\", \"email\": \"${user.email}\", \"status\": \"active\"}'}"
},
{
"name": "call2",
"connection": "acctAuth",
"basicUrl": "api.duosecurity.com",
"hostUrl": "/admin/v1/users/enroll",
"url": "https://api.duosecurity.com/admin/v1/users/enroll",
"httpMethod": "POST",
"httpParams": "{\"email\": \"${user.email}\", \"username\": \"${user.username}\"}",
"successResponses": {
"statusCode": [
200,
400
]
}
}
]
}

Please let me know in case you require any further information.

sudeshjaiswal
Saviynt Employee
Saviynt Employee

Hello @GauravJain,

Seems responseColsToPropsMap was wrongly mapped that the reason you where getting this exception.
"Exception in restProvisioningService-updateAccFromProvMetadata try: org.codehaus.groovy.runtime.metaclass.MissingPropertyExceptionNoStack: No such property: accountType for class: com.saviynt.ecm.identitywarehouse.domain.Accounts"

Please update the "responseColsToPropsMap " accordingly.
Sample json

 

{
	"accountIdPath": "call1.message.response.user_id",
	"dateFormat": "yyyy-MM-dd'T'HH:mm:ssXXX",
	"responseColsToPropsMap": {
		"customproperty32": "call1.message.status~#~char",
		"customproperty2": "call1.message.response.email~#~char",
		"displayName": "call1.message.response.realname~#~char",
		"status": "#CONST#Active~#~char",
		"name": "call1.message.response.username~#~char"
	},
	"call": [
		{
			"name": "call1",
			"connection": "acctAuth",
			"basicUrl": "api.duosecurity.com",
			"hostUrl": "/admin/v1/users",
			"url": "https://api.duosecurity.com/admin/v1/users",
			"httpMethod": "POST",
			"httpParams": "{\"username\": \"${user.username}\", \"realname\": \"${user.displayname}\", \"email\": \"${user.email}\", \"status\": \"active\"}"
		},
		{
			"name": "call2",
			"connection": "acctAuth",
			"basicUrl": "api.duosecurity.com",
			"hostUrl": "/admin/v1/users/enroll",
			"url": "https://api.duosecurity.com/admin/v1/users/enroll",
			"httpMethod": "POST",
			"httpParams": "{\"email\": \"${user.email}\", \"username\": \"${user.username}\"}",
			"successResponses": {
				"statusCode": [
					200,
					400
				]
			}
		}
	]
}

 

 Thanks,

If you find the above response useful, Kindly Mark it as "Accept As Solution".

Thanks @sudeshjaiswal for your quick revert. I am now using following configuration for CreateAccountJson (includes your above suggestion as well) but still have following issues:

1) "status" column is showing value as "Manually Provisioned" instead of "Active" as returned from Duo api call

2) customproperty10 is not getting populated with status value returned from duo api call

3) inside httpParams why the binding values are not getting executed. For example i am passing \"email\": \"${user.email}\" which is being passed as it is in the api call instead of its actual value in user object.

 

{
"accountIdPath": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? 'call1.message.response.admin_id' :'call1.message.response.user_id'}",
"dateFormat": "yyyy-MM-dd'T'HH:mm:ssXXX",
"responseColsToPropsMap": {
"status": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? '#CONST#Active~#~char' : 'call1.message.status~#~char'}",
"displayName": "call1.message.response.realname~#~char",
"name": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser'))?'call1.message.response.email~#~char' : 'call1.message.response.username~#~char'}",
"created_on": "call1.message.response.created~#~datesec",
"customproperty9": "call1.message.response.is_enrolled~#~char",
"customproperty10": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? '#CONST#Active~#~char' : 'call1.message.status~#~char'}"
},
"call": [
{
"name": "call1",
"connection": "acctAuth",
"basicUrl": "api.duosecurity.com",
"hostUrl": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? '/admin/v1/admins' : '/admin/v1/users'}",
"url": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ?'https://api.duosecurity.com/admin/v1/admins' : 'https://api.duosecurity.com/admin/v1/users'}",
"httpMethod": "POST",
"httpParams": "{\"username\": \"${user.username}\", \"realname\": \"${user.displayname}\", \"email\": \"${user.email}\", \"status\": \"active\"}"
},
{
"name": "call2",
"connection": "acctAuth",
"basicUrl": "api.duosecurity.com",
"hostUrl": "/admin/v1/users/enroll",
"url": "https://api.duosecurity.com/admin/v1/users/enroll",
"httpMethod": "POST",
"httpParams": "{\"email\": \"${user.email}\", \"username\": \"${user.username}\"}",
"successResponses": {
"statusCode": [
200,
400
]
}
}
]
}

sudeshjaiswal
Saviynt Employee
Saviynt Employee

Hello @GauravJain,

Please try with the  below  json,

{
"accountIdPath": "${(requestAccessAttributes?.get('Account_Type') != null && requestAccessAttributes?.get('Account_Type')?.equals('AdminUser')) ? 'call1.message.response.admin_id' : 'call1.message.response.user_id'}",
"dateFormat": "yyyy-MM-dd'T'HH:mm:ssXXX",
"responseColsToPropsMap": {
"accountsStatus": "${(requestAccessAttributes?.get('Account_Type') != null && requestAccessAttributes?.get('Account_Type')?.equals('AdminUser')) ? '#CONST#Active~#~char' : 'call1.message.status~#~char'}",
"displayName": "call1.message.response.realname~#~char",
"name": "${(requestAccessAttributes?.get('Account_Type') != null && requestAccessAttributes?.get('Account_Type')?.equals('AdminUser'))?'call1.message.response.name~#~char' : 'call1.message.response.username~#~char'}",
"accountType": "${(requestAccessAttributes?.get('Account_Type') != null && requestAccessAttributes?.get('Account_Type')?.equals('AdminUser')) ? '#CONST#AdminUser~#~char' : '#CONST#EndUser~#~char'}",
"accountRole": "call1.message.response.role~#~char"
},
"call": [
{
"name": "call1",
"connection": "acctAuth",
"basicUrl": "api.duosecurity.com",
"hostUrl": "${(requestAccessAttributes?.get('Account_Type') != null && requestAccessAttributes?.get('Account_Type')?.equals('AdminUser')) ? '/admin/v1/admins' : '/admin/v1/users'}",
"url": "${(requestAccessAttributes?.get('Account_Type') != null && requestAccessAttributes?.get('Account_Type')?.equals('AdminUser')) ? 'https://api.duosecurity.com/admin/v1/admins' : 'https://api.duosecurity.com/admin/v1/users'}",
"httpMethod": "POST",
"httpParams": "${(requestAccessAttributes?.get('Account_Type') != null && requestAccessAttributes?.get('Account_Type')?.equals('AdminUser')) ? '{\"name\": \"${user.firstname} ${user.lastname}\", \"realname\": \"${user.firstname} ${user.lastname}\", \"email\": \"${user.email}\", \"status\": \"active\", \"role\":\"${requestAccessAttributes.Role}\",\"password\":\"${password}ixnm\", \"phone\":\"${requestAccessAttributes.MobileNumber}\"}' : '{\"username\": \"${user.email.substring(0,user.email.lastIndexOf(\"@\"))}\", \"realname\": \"${user.firstname} ${user.lastname}\", \"email\": \"${user.email}\", \"status\": \"${requestAccessAttributes.Status}\"}'}"
},
{
"name": "call2",
"connection": "acctAuth",
"basicUrl": "api.duosecurity.com",
"hostUrl": "/admin/v1/users/enroll",
"url": "https://api.duosecurity.com/admin/v1/users/enroll",
"httpMethod": "POST",
"httpParams": "{\"email\": \"${user.email}\", \"username\": \"${user.email.substring(0,user.email.lastIndexOf(\"@\"))}\"}",
"successResponses": {
"statusCode": [
200,
400
]
}
}
]
}

 Thanks

If you find the above response useful, Kindly Mark it as "Accept As Solution".

Hi

Its still not working. Replaced "Account Type" with "Account_Type" as suggested and username with email substring. Now getting below error in logs.

secondly, i just tried removing email from param list and it created an account with this name "${user.username}" instead of using the actual value. very weird behavior. Can we open a support ticket to debug this case?

 

Exception in signRequest :
 
2024-03-04T19:05:21+05:30-ecm-worker--null-sjsbx--com.fasterxml.jackson.core.JsonParseException: Unexpected character ('@' (code 64)): was expecting comma to separate Object entries at [Source: {"username": "${user.email.substring(0,user.email.lastIndexOf("@"))}", "realname": "${user.displayname}", "email": "${user.email}", "status": "active"}; line: 1, column: 65] at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1702) at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:558) at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:456) at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._skipComma(ReaderBasedJsonParser.java:2285) at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextFieldName(ReaderBasedJsonParser.java:912) at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringKeyMap(MapDeserializer.java:505) at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:362) at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:27) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3814) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2877) at com.saviynt.provisoning.rest.RestProvisioningService.canonRequest(RestProvisioningService.groovy:3870) at com.saviynt.provisoning.rest.RestProvisioningService.signRequest(RestProvisioningService.groovy:3835) at com.saviynt.provisoning.rest.RestProvisioningService.populateHttpParamsForBasicWithHmac(RestProvisioningService.groovy:3598) at com.saviynt.provisoning.rest.RestProvisioningService.populateHttpParams(RestProvisioningService.groovy:3454) at com.saviynt.provisoning.rest.RestProvisioningService.createNewUser(RestProvisioningService.groovy:2725) at com.saviynt.provisoning.rest.RestProvisioningService$_createAccount_closure14.doCall(RestProvisioningService.groovy:2148) at com.saviynt.provisoning.rest.RestProvisioningService.createAccount(RestProvisioningService.groovy:1981) at com.saviynt.ecm.services.ArsTaskService.createAccountTarget(ArsTaskService.groovy:11728) at com.saviynt.ecm.services.ArsTaskHelperService$_whenTaskTypeIsThreeNewAccountAccess_closure50.doCall(ArsTaskHelperService.groovy:3075) at com.saviynt.ecm.services.ArsTaskHelperService.whenTaskTypeIsThreeNewAccountAccess(ArsTaskHelperService.groovy:3066) at com.saviynt.ecm.services.ArsTaskHelperService$_completeAutoProvTasksUpgraded_closure1.doCall(ArsTaskHelperService.groovy:175) at com.saviynt.ecm.services.ArsTaskHelperService.completeAutoProvTasksUpgraded(ArsTaskHelperService.groovy:160) at MultipleProvisioningJob.execute(MultipleProvisioningJob.groovy:222) at org.quartz.core.JobRunShell.run(JobRunShell.java:199) at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:546)

sudeshjaiswal
Saviynt Employee
Saviynt Employee

Hello @GauravJain ,

Can you please try with the below json,  the "Account Type", you need to copy it from the endpoint dynamic attribute, whay you have mentioned.

{
	"accountIdPath": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? 'call1.message.response.admin_id' :'call1.message.response.user_id'}",
	"dateFormat": "yyyy-MM-dd'T'HH:mm:ssXXX",
	"responseColsToPropsMap": {
		"accountsStatus": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? '#CONST#Active~#~char' : 'call1.message.status~#~char'}",
		"displayName": "call1.message.response.realname~#~char",
		"name": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser'))?'call1.message.response.email~#~char' : 'call1.message.response.username~#~char'}",
		"accountType": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? '#CONST#AdminUser~#~char' :'#CONST#EndUser~#~char'}",
		"accountRole": "call1.message.response.role~#~char"
	},
	"call": [
		{
			"name": "call1",
			"connection": "acctAuth",
			"basicUrl": "api.duosecurity.com",
			"hostUrl": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? '/admin/v1/admins' : '/admin/v1/users'}",
			"url": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ?'https://api.duosecurity.com/admin/v1/admins' : 'https://api.duosecurity.com/admin/v1/users'}",
			"httpMethod": "POST",
			"httpParams": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? '{\"name\": \"'+user.displayname+'\", \"email\": \"'+user.email+'\", \"status\": \"active\"}' : '{\"username\": \"'+user.username+'\", \"realname\": \"'+user.displayname+'\", \"email\": \"'+user.email+'\", \"status\": \"active\"}'}"
		},
		{
			"name": "call2",
			"connection": "acctAuth",
			"basicUrl": "api.duosecurity.com",
			"hostUrl": "/admin/v1/users/enroll",
			"url": "https://api.duosecurity.com/admin/v1/users/enroll",
			"httpMethod": "POST",
			"httpParams": "{\"email\": \"${user.email}\", \"username\": \"${user.username}\"}",
			"successResponses": {
				"statusCode": [
					200,
					400
				]
			}
		}
	]
}


Thanks.




If you find the above response useful, Kindly Mark it as "Accept As Solution".

Hi @sudeshjaiswal thanks for your revert. Earlier i was using dynamic attribute name as mentioned in my endpoint "Account Type" but got confused with one example config. but, the last config you have shared is working absolutely fine - the only change i made was to rename "accountType" to "accounttype".

one thing i want clarity on is when to use "$" expression and when "'+user.email"? why this expression \"${user.email}\" was not getting evaluated in earlier config? i checked developer handbook to understand this but its not explained there.

secondly, if i have to pass status as selected on request from "requestAccessAttributes" then i tried with this config but didn't work - got some json format error

"httpParams": "${(requestAccessAttributes?.get('Account Type') != null && requestAccessAttributes?.get('Account Type')?.equals('AdminUser')) ? '{\"name\": \"'+user.displayname+'\", \"email\": \"'+user.email+'\", \"status\": \"active\"}' : '{\"username\": \"'+user.username+'\", \"realname\": \"'+user.displayname+'\", \"email\": \"'+user.email+'\", \"status\": \"${requestAccessAttributes.get('Status')}\"}'}"

should i use it as this \"status\": \"'+requestAccessAttributes.get('Status')+'\"

3rd - is it possible to make call2 only if call1 is successful? During testing i saw even if call1 gets failed (because of incorrect syntax) then call2 gets triggered successfully and the request is marked as completed. in one another case i observed that if call1 gets failed for n times then saviynt triggers call2 and marks request as complete. how to manage such issues?

Regards

Gaurav

 

sudeshjaiswal
Saviynt Employee
Saviynt Employee

Hello @GauravJain,

Firstly, thank you for bringing it up. We will update the template accordingly.

The JSON  "httpParams" code above uses a Groovy's interpolation feature, allowing you embedding the the  expressions within strings using "${  }".
However, in the provided previous jsons which where failing because expressions were embedded within the expression, because of the that variables where not getting resolved.

2nd:  if i have to pass status as selected on request from "requestAccessAttributes" then i tried with this config but didn't work - got some json format error


You Should not use $ anywhere inside the expression as $ is already mentioned would request you to use below  attribute for status,
\"status\": \"'+requestAccessAttributes.Status+'\

3rd - is it possible to make call2 only if call1 is successful? During testing i saw even if call1 gets failed (because of incorrect syntax) then call2 gets triggered successfully and the request is marked as completed. in one another case i observed that if call1 gets failed for n times then saviynt triggers call2 and marks request as complete. how to manage such issues?

No, it possible to make call2 only if call1 is successful.
As it goes in the order.

Thanks

 

If you find the above response useful, Kindly Mark it as "Accept As Solution".

Thanks @sudeshjaiswal for your revert.

I will try the suggestion in poin #2 and confirm back.

For point #3, i think you mean its not possible and the calls are triggered in the given order.

Regards

Gaurav

Hi @sudeshjaiswal Suggestion mentioned in Point #2 worked fine.

For point #3, i think you mean its not possible and the calls are triggered in the given order. correct?

Regards

Gaurav

 

Hello @GauravJain,

Thanks for the confirmation,
Yes, it gets processed in the sequential order.

Thanks,


If you find the above responses of this useful, kindly consider selecting Accept As Solution and clicking on the kudos button.
If you find the above response useful, Kindly Mark it as "Accept As Solution".

Thanks @sudeshjaiswal for confirmation.

i have raised another forum for account deletion issue. Please have a look.

Duo account deletion issue - Saviynt Forums - 81089

I will close this post.

Please share final working JSON


Regards,
Rushikesh Vartak
If you find the response useful, kindly consider selecting Accept As Solution and clicking on the kudos button.