Sunday, July 11, 2021

Mechanism Behind Implementing the Single Sign on (SSO) using SAML between Identity Provider (IDP) and Service Provider(SP)

Thought Process behind this implementation


While implementing Single Sign on in one of the project , I realized before implementing that anyone should have the clear concept about protocol like SAML, some terms like Identity Provider (IDP) and Service Provider (SP) and most important  - why should we use Single Sign On and what kind of benefit it can give to the Business users. Lastly How will it Work.

Use Case


As a Business user Some one has to use two different Application simultaneously for instance you can think about Salesforce , Gmail or any other pricing Systems . So it's very difficult and at the same time annoying to login again again using different credentials. So if we can think of something by which user can be able to login two different Application using one Common Credential, it would be very beneficial for the Business users in-terms of Simplicity and maintainability. 

Concept


Before start on anything first we should know What is SAML and some common key factor or terminology about SAML.
  • SAML :
  1.           Security Assertion Markup Language
  2.           Commonly used for Single-Sign-On(SSO)
  3.           Used in Many Places
  4.           AS it used XML based open standard , so it’s very easy to adopt.

  • Some of  Key Terminology Which we should know before implementing SAML

          

    

  • Service Provider Initiated Flow : 

When User is trying to access the any resources from server ( in our case we can take salesforce as an example), there are some connection is being made between Identity Provider (IDP) and Service Provider (SP), those are : -
  1. User trying to access the resources form SP (example. Salesforce)
  2. Salesforce sends the SAML Request (Authentication Request)  to IDP (example. Azure) in xml format with certain parameters to authenticate the user. It will flow in XML format with encoded value in query string.
  3. After authentication is being done at IDP end, IDP sends SAML Response to SP with the addition of other extra information.
  4. If the authentication is being done successfully , user will be able access the resources.
        Please find the diagram below to understand the flow in a better way : -






    Please find the example of SAML Request below and the some of important keys to remember : 


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" 
					xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" 
					//Unique id generated by Service Provider and Identity Provider will respond to that id in the SAML response. 
					ID=" _0f551f9288c8b76f21c3d4d15c9cd1df1290476801091" 
					Version="2.0" 
					ProviderName="SP test" 
					//It’s a time stamp when request is being sent. Also, at the same time if any particular time frame already been defined at IDP end, then it will only accept the request between the defined time frame only.
					IssueInstant="2014-07-16T23:52:45Z"
					//It’s an Identity Provider end point URL where the SAML Request supposed to flow. Also, a point of verification by which Identity provider can check about the correct recipient. 
					Destination="http://idp.example.com/SSOService.php" 
					ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" 
					//ASC is the address which identifies where the SAML Response should go after the Authentication in being done. It’s another point of verification.
					AssertionConsumerServiceURL=" https://MyDomainName.my.salesforce.com?so=00Dx00000000001" ">
	//It’s a part of Identity provider to verify and build the SAML trust between IDP and SP.				
	<saml:Issuer> https://myidp.my.salesforce.com </saml:Issuer>
	<samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" AllowCreate="true"/>  
</samlp:AuthnRequest>



     Please find the example of SAML Response below and the some of important keys to remember :


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
<samlp:Response 
				//It holds the addreses where the Response should go, It's Specified as AssertionConsumerServiceURL in SAML Request
				Destination="https://MyDomainName.my.salesforce.com?so=00Dx00000000001"
				//This i scoming is a part of SAML Request from SP
				ID="_0f551f9288c8b76f21c3d4d15c9cd1df1290476801091"
				//This id generated by IDP to make it unique
				InResponseTo="_2INwHuINDJTvjo8ohcM.Fpw_uLukYi0WArVx2IJD569kZYL
							  osBwuiaSbzzxOPQjDtfw52tJB10VfgPW2p5g7Nlv5k1QDzR0EJYGgn0d0z8
							  CIiUOY31YBdk7gwEkTygiK_lb46IO1fzBFoaRTzwvf1JN4qnkGttw3J6L4b
							  opRI8hSQmCumM_Cvn3DHZVN.KtrzzOAflcMFSCY.bj1wvruSGQCooTRSSQ"
				IssueInstant="2010-11-23T01:46:41.091Z" Version="2.0">
	
	//It's the issuer string , bacically the the Entity Id of IDP, it's an another parameter for building SAML trust.
<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">
		https://myidp.my.salesforce.com
</saml:Issuer>

<samlp:Status>
	<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>

<saml:Assertion ID="_e700bf9b25a5aebdb9495fe40332ef081290476801092" IssueInstant="2010-11-23T01:46:41.092Z" Version="2.0">
	<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://exampleidp.com</saml:Issuer>

	//This where IDP are putting informaiton about the user by the assertion, each should have signed digitally.
	<ds:Signature> 	
		<ds:SignedInfo>
			<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
			<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
			<ds:Reference URI="#_0f551f9288c8b76f21c3d4d15c9cd1df1290476801091">
				<ds:Transforms>
					<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
					<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
					<ec:InclusiveNamespaces PrefixList="ds saml samlp xs"/>
				</ds:Transform>
				</ds:Transforms>
				<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
				<ds:DigestValue>4NVTbQ2WavD+ZBiyQ7ufc8EhtZw=</ds:DigestValue>
			</ds:Reference>
		</ds:SignedInfo>
		<ds:SignatureValue>	ExampleSamlSignature</ds:SignatureValue>
		<ds:KeyInfo>
			<ds:X509Data>
			//The certificate which is being used for signing.
				<ds:X509Certificate>ExampleX509 Certificate</ds:X509Certificate>
			</ds:X509Data>
		</ds:KeyInfo>
	</ds:Signature>

	<saml:Subject>
		//In the subject , it use to store the information about the user who is signing in, like user Id . 
		<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">exampleuser@salesforce.com</saml:NameID>
		<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
			<saml:SubjectConfirmationData NotOnOrAfter="2010-11-23T01:51:41.093Z" Recipient="https://MyDomainName.my.salesforce.com?so=00Dx00000000001"/>
		</saml:SubjectConfirmation>
	</saml:Subject>

	//Condition is speified to mention the window abount how long the response are valid.
	<saml:Conditions NotBefore="2010-11-23T01:46:41.093Z" NotOnOrAfter="2010-11-23T01:51:41.093Z">
		<saml:AudienceRestriction>
			<saml:Audience>https://exampleserviceprovider.com</saml:Audience>
		</saml:AudienceRestriction>
	</saml:Conditions>

	<saml:AuthnStatement AuthnInstant="2010-11-23T01:46:41.092Z">
		<saml:AuthnContext>
			<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
		</saml:AuthnContext>
	</saml:AuthnStatement>

	///In this section , it usually store the user information like user Name , Profile etc.
	<saml:AttributeStatement>
		<saml:Attribute Name="userId" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
			<saml:AttributeValue xsi:type="xs:anyType">005D0000001Ayzh</saml:AttributeValue>
		</saml:Attribute>

		<saml:Attribute Name="username" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
			<saml:AttributeValue xsi:type="xs:anyType">admin@identity.org</saml:AttributeValue>
		</saml:Attribute>

		<saml:Attribute Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
			<saml:AttributeValue xsi:type="xs:anyType">exampleuser@salesforce.com</saml:AttributeValue>
		</saml:Attribute>

		<saml:Attribute Name="is_portal_user" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
		<	saml:AttributeValue xsi:type="xs:anyType">false</saml:AttributeValue>
		</saml:Attribute>
	</saml:AttributeStatement>
</saml:Assertion>

</samlp:Response>


  • Identity-Provider Initiated Flow : 
  1. User is trying to access the recourse directly from the Identity Provider rather from SP.
  2. Let’s say we have a salesforce App already built in Azure.
  3. User is trying to access the App from there itself.
  4. So, only one flow will be sending from Identity Provider to Service Provider i.e. SAML Response.
  5. We don’t need SAML Request any where in this Flow.
  6. The structure of the SAML Request remain as it is like before. (Whatever mentioned in the SP initiated flow) 

      Please find the diagram below to understand the flow in a better way : 






  • Note : 
Once the SSO is being configured , we get to see in some of cases, there are some mismatches in the user information's between IDP and SP. There are two possible scenarios for which it can happen and those are : -

  1. Either new User has been created .
  2. Otherwise some attributes gets updated after setting up the SSO.

we can handle those as well, by using below two options : -

  1. When IDP is sending the response we can use Just In Time (JIT) for creation or to update the User attributes.
  2.  we Can built separate real time integration channel , so that whenever there will be an update it will update the same at SP end.

References:



Friday, July 2, 2021

Salesforce and QUIP integration using REST API

Thought Process behind this implementation 

Hi all, it has been long time since I posted something. So, today’s topic is bit interesting - how Someone can use Quip REST API from salesforce and as it is a new add-on functionality, so the number information is limited on the authentication mechanism. I will be trying to explain this with a business use case, so that in future someone can relate their requirements very easily. 

Use Case 

We have a quip Template in place which is currently storing the Account Plan related data for that account. As we have so many numbers of Accounts in the Org, it is very difficult to search those documents in Quip portal once those are created. So, the next thought came into our mind to keep those documents in a proper logical way, that could be anything based on how your current Accounts are being segregated. The folder name would be your Account Name, by which you quip user can easily recognize the document. Now it is very difficult to create those folders manually, so somehow, we should manage to create those Folders via some automation by implementing Quip REST API. The possible scenario would when user will be generating the document in salesforce, the folder Should be created on that action itself.

Let say we are having a field at Account object name is Type having three options, those are: -

·       Customer

·       Prospect

·       Other

Now these are the predefined valued so we can create those folders beforehand in Quip Portal , but we don’t know which Account is going to have which type , so the Account Folder under each Type will be created dynamically.

Please refer the below snap for your better understanding: -






How Architecture works behind


1.       Create the folder structure colored as blue mentioned in the above diagram.

2.       Automation API and Admin API.

3.       To create New API Key on Your Quip Site.

4.       Grant a Quip Admin API Access for the User which will be used to call Rest API service from Salesforce.

5.       Authorization can be done by to ways, to get the access token, those are: -

a.       Use Postman to get the access token.

b.       User your visual force page to get the access token.

6.       Once you have the access token, you can call the rest API service defined by QUIP based on your needs.


Process to implement

 

·       Automation API and Admin API


The automation API allows you to make API calls on threads that the user has access to, and Admin API allows access to all threads against the entire site. Admin also has few additional endpoints around Events API, Governance policies, quarantine, admin roles, etc. As for the token generation, we can use the /dev/token URL

for automation and we can have the domain authentication for an admin API token.     

 

·       To create New API Key on Your Quip Site


As discussed, first we need to create the API key in quip portal.

Navigate to the Admin Portal > Settings > Integrations > New API Key.

To stay organized, select a name for the key that will make it obvious what it was used for. It will look like below: -














·       Grant a Quip Admin API Access for the User which will be used to call Rest API service from Salesforce.


1.       Go to the Admin Console > Site Settings > Admin Roles.

2.       Select Create New Role

3.       Name Role and select your desired permissions for each category, including Admin API Access > Edit.

4.       Assign this Role to the Admin or Admins you would like to be able to manage API Access.

5.       That admin will see a new section in the Site Settings page of their admin console.

6.       Click Grant Access to provide access to a user entering email and access level.

7.       To edit or revoke access using the dropdown menu from the right of the user row.


·       Access Token Generation


1.      There is a concept of Dev Toke, which is basically nothing but act like an access toke, but it’s only for developer to test their functionality only, It’s user specific and developer should only use this for testing purpose only. We do not need to perform the second (above) step to achieve this.  Please adjust the quip portal URL to get the dev token: -

https://xxx.quip.com/dev/token

 

Now you can use it as access token to hit the QUIP rest API resources.


2.      Use Postman to get the access token: -

 

Pull the latest and download and open Postman. https://www.getpostman.com/downloads/

 

Step by step instructions to download and install can be found here - https://www.guru99.com/postman-tutorial.html


a.)    Once postman in installed, create a new request – 




                        b.) Create a name for the request and select a collection or folder to save these requests.




                            c.) Now, let us connect postman to your Quip instance.
                            Click on Auth and select OAuth 2.0 and click on Get new access token.




                     d.) Grant Type= Authorization code.

                ·       Callback URL: https://platform.quip.com

                ·       Authorize URL: https://platform.quip.com/1/oauth/login

                ·       Access Token URL: https://platform.quip.com/1/oauth/access_token

                ·       Quip Client ID  (Already generated in Process implementation section)

                ·       Quip Client Secret (Already generated in Process implementation section).




                        e.) You will see the login to Quip. Give your login information and you are ready to  us the API.



Calling Quip Rest API endpoints based on the requirement: -

 

Once you will have the access token and security token, we just need to follow the documentation to call the respective API end points based on the requirements. 

Please refer the below generic function which can be called from another trigger or Apex class:



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
  Method Name : createNewFolder
  Input Parameters : accName, parent folder Id (which created earlier).
  purpose : It will take account name and parent folder id as a parameter and using rest api call created the new folder at th quip portal.
 */

public static void createNewFolder(string accName, String parentFolderId) {
	try{           
		if(parentFolderId != null && accName != null){
			HttpRequest req2 = new HttpRequest();
			req2.setMethod('POST');
			
			// End point for creating new folder
			req2.setEndpoint('https://platform.quip.com/1/folders/new');
			//Access toke which we already got using postman
			String authHeader = 'Bearer '+access_token;
			req2.setHeader('Authorization', authHeader);
			//the parameters should be pass within the body
			String body2 = 'title='+accName+'&parent_id='+parentFolderId;
			req2.setBody(body2);
			Http http2 = new Http();
			HTTPResponse res2 = http2.send(req2);
			System.debug(res2.getBody());			
		}
	}Catch(System.CalloutException e){
		System.debug('Error-' + e.getMessage());   
	}
}
    



·       Note: -


Quip provides two standard roles  -  Site Admin and Super Admin. Out of those, only Super Admin role will have the provision to create custom roles.


Quip is only offering OAuth 2.0 Web Server Flow for authorization which needs user intervention to generate the access token and in our use case we do not have the provision for user intervention. We had a discussion with Quip technical team, and they agreed that for now they don’t have any server-to-server authorization mechanism and we should generate the access token beforehand either using postman or using other component (you can use visual force page as well)

The access token is valid for 30 days and refresh token is valid for 10years, so we recommend constantly generating new access tokens every 28 days or so using the token endpoint. The dev token for automation API is valid for 365 days unless new tokens are generated invalidating the older one.


References: