Place custom button on Registration Page in Dynamics 365 Portals

Recently I had a requirement where my customer wanted to put a Cancel button in the registration screen of Dynamics 365 Portal. To explain the requirement, the OOB screen looks like below.

image

What my customer wanted was to place the Cancel button beside the Register button. So that when he clicks on the Cancel button, it should throw the user back to the login page.

So let’s see how to do it.

Step 1: Create a content snippet

Go to settings –> portals –> content snippets

Create a content snippet with Name = Account/Register/PageCopy and Type = HTML. Check for the below screenshot

image

Save the record.

 

Step 2: Write the content of the HTML to render the Cancel button

Copy and paste the below in the Value (HTML) field

$(document).ready(function () {

$submitButton = $(“#ContentContainer_MainContent_MainContent_SecureRegister”).find(“#SubmitButton”);

$submitButton.parent().append(“<input type=’button’ id=’btn_cancel’ class=’btn btn-primary’ value=’Cancel’ />”);

$(“#btn_cancel”).click(function () {

window.location.href = “https://xrmforyou.microsoftcrmportals.com&#8221;;

});

});

 

There is one trick here. If you just Copy/ Paste the above code in the HTML field, it will render as text on the Registration Page.

image

So the trick is to follow the below steps before copy/ pasting the above code.

Click on the Source Icon as highlighted below. Once you click, it becomes a HTML editor.

image

Now copy and past the above code.

Save and refresh your portal.

image

 

Hope this helps!

 

Debajit Dutta

(Dynamics MVP)

For corporate training/ consulting, please write to us at info@xrmforyou.com

Advertisements

Security Nuances with Manager Based Hierarchy in Dynamics 365

Manager Hierarchy was introduced way back with 2015 Online Update 1. And you might be wondering why this blog after years this feature has been introduced?

Well I can assure you, you won’t be disappointed after reading this blog. In this blog I will explain in detail the manager security nuances from my personal experience with project implementations and training. I am not going to explain how Manager security works. I am just going to explain the security nuances and how it works in multiple scenarios.

To explain my point, I have the below data set-up in my environment.

1. Business Unit Set-up

  • Americas –> Child BU of Root BU
  • North America –> Child BU of Americas

2. User Set-up

  • User A belonging to Americas BU
  • User B belonging to North America and reporting to User A
  • User C belonging to North America

3. Created Custom Entity named – Manager Hierarchy Test

4. Security Roles

  • Manager Role – having User level access on all privileges on the entity Manager Hierarchy Test
  • Reportee Role – having BU level access on all privileges on the entity Manager Hierarchy Test

5. User A is assigned Manager role and User B and User C having Reportee Role

So Manager Hierarchy affects which record? To put in my words

  • Owned by Reportee
  • Shared to Reportee
  • Owned by a team to which Reportee is a team member
  • Shared by a team to which Reportee is a team member

Which records are not affected by Manager Hierarchy ?

To put in simple terms, any of the records which does not meet the above four conditions is not affected by Manager Hierarchy. So the records which the reportee gains access due to his security prvileges (Business Unit/ Parent child/ organization) are not affected by this. Confused? Don’t worry. We will come back to this.

 

So let’s take these scenarios one by one.

Scenario 1:

Record owner = Reportee

User B creates a record – ‘Record for User B’. So this record is being owned by User B.  As per Manager Hierarchy, user A is able to read/ write this record since User B is direct reportee of User A. No surprises here right. After all everyone knows that.

First of all, to have write access to the reportee record, User A should be having at-least user level write privilege on the entity through his security role. Otherwise he won’t be able to write the reportee’s record even through Manager Hierarchy.

Also another point –Delete” privilege is not part of Manage security. Hence Manager won’t be able delete the reportee’s record.

 

Scenario 2:

Record shared to Reportee

Another user shares a record with User B with all the privileges – Read/ write/ append/ append to/ share. User A will now see this record because of Manager Hierarchy. However although the reportee have all the privileges on this record by virtue of sharing, through Manager Hierarchy, User A will only have read-only access to this record.

 

Scenario 3:

Record owned by a team which the reportee is member of

this behavior is same as Scenario1

 

Scenario 4:

Record Shared to a team which the reportee is member of

This behavior is same as Scenario 2

 

Now say for example User C goes ahead and creates record. Since User B and User C are both in the same business Unit (North America in example here), by virtue of their business unit read privilege on security role, User B would be able to see the record. However since User B is not the owner/ not shared to him/ not owned by the team to which he belongs/ not shared to the team to which he belongs, this record is not affected by Manager hierarchy and hence User A is not able to view this record.

 

Hope this clears out any doubt with Manager Hierarchy.

Debajit Dutta

(Dynamics MVP)

For corporate training/ consulting, please reach out to us at info@xrmforyou.com or visit our website – xrmforyou.com

{Quick Tip} Restrict To Lookup of email to allow only a record in Dynamics 365

Nothing like real time requirements and here is another one. Customer walks in and puts in his requirement – “Users should not be able to select more than one record in the To field of CRM”. We suggested that while sending the email, we would put a validation which would stop the user from sending the email if more than one record is there. Well as everybody knows, more often than not, customer has his way and then we were back to the drawing boards trying to figure out how to do it.

For starters, To field in Dynamics allows you to select more than one record of multiple entity types which is obvious isn’t it. Below is the UI which allows you to do that.

image

 

Fortunately we found out a way. This is what we did.

  • Created a solution. Added Email entity and the To field to it.
  • Exported the solution
  • Unzipped the solution and opened up customizations.xml file in a XML editor.
  • Navigated to the area where To attribute is there in the XML file.

image

  • Added the below in the XML file just above <displaynames> tag.

<LookupStyle>single</LookupStyle>

  • Re-zipped the files. Imported the solution back and Publish all customizations.
  • And now when you click the To field, this is what you get.

image

 

Mission accomplished!

Hope this helps.

 

Debajit Dutta

(Dynamics MVP)

For training/ consulting, please write to us at info@xrmforyou.com

{Quick Tip} Restrict From Lookup in Dynamics 365 email to only queue–Without addCustomFilter or Unsupported Jscript

This is an old topic which is getting discussed since CRM 2011 or I think even before that. You must be wondering, why I am digging out history here. Well there has been so many blogs written about this.

So what’s the problem statement here?

Recently my customer wanted that whenever an email is being sent from Dynamics, it only needs to be sent through Queues. In other words in the From Lookup of the email, the user should not be able to select self or any other user from CRM.

So there are basically two steps to it. Since from is a multi-entity lookup, it shows both the user and queue when user tries to select.

So the first thing needed is to stop the user from selecting the user entity and the next is to stop the user from selecting any user record in from.

To achieve the first problem statement, so many blogs have been written but they use unsupported Javascript to meddle with the UI element and disable the dropdown. We will not do that here.

The other option, supported way, is to use the addCustomFilter. But with that, even though you stop from selecting a user, still the Entity selection of User/ Queue is available.

So wanna try something new? Let’s do this.

  • Create a solution and add the Email entity to it. While adding the entity, to keep the solution simple, just add the from field to it (only for CRM 2016 and above. Prior versions, you are not luck to choose the options)
  • Export the solution as Unmanaged
  • Unzip the solution. You should see three file
    • Customization.xml
    • Solution.xml
    • [Content_types].xml
  • Open the Customization.xml in a XML editor of your choice and navigate to the section where the From field is present.

image

  • You may find the unmodified=”1” in the attribute element as well as Email entity element. Remove the tags. Otherwise any changes you make here may not reflect in CRM once you import back.
  • Scroll down a bit and you will see the section with the LookupType tag.

image

  • Remove the entire element corresponding to 8 (Type code for user). Your final XML should just contain the one LookupType tag with Queue (2020).
  • All set and done, select the three files and re-zip them

image

  • Re-import the solution and publish all customizations.
  • Now go back to your CRM email. Try to select “from”. And get the delight. Now entity selection is disabled and you are just left with selecting the queue.

image

Headless Authentication with Dynamics CRM online and External Web App which requires Client Secret

As promised, I am back to my second post on this topic. In my previous post, I showed you on how to generate Authorization token of D365 online from Native Console App using the Client_ID.

https://debajmecrm.com/2018/04/29/headless-authentication-with-dynamics-crm-online-web-api-without-user-login-screen-without-using-adal-part-i/

We did that using simple HttpWebRequest and Response and did not use the ADAL (Active directory authentication library) as well.

Well, let’s dive deep here. Nothing big in my previous topic as the same thing can be done using ADAL and in a clean way as well. Then why use that construct?

We are talking of headless authentication here which means authentication without user intervention. Using ADAL, it was fine to generate the token from a Native console APP using the Client ID. However situations become complex when we try to do the same from an external Web Application which required the Client_Secret as well for generating the token.

So I created a ASP.NET web application and registered in Azure. I got the client id and client secret after registering the Web App. How to do that? Well you have many wonderful blogs out there and I am not going to repeat the same.

Now comes the code part. Below is the code for the same. Look at highlighted line to check how I am passing the client id and client secret

My CRM URL is – https://xrm4u1.crm.dynamics.com

 

public string GetCRMToken()
{

var azureTenantId= “xrm4u1.onmicrosoft.com”;
var clientId = “<client id of the Web app after registering in azure>”;

var clientSecret = “<client secret of the Web App after registering in azure>”;
var requestUrl = string.Format(@”
https://login.microsoftonline.com/{0}/oauth2/token”,
azureTenantId);

var url = “https://xrm4u1.crm.dynamics.com”;
            var userName = “<username>”;
var password = “<password>”;

            // Connect to the authentication server

            var request = (HttpWebRequest)WebRequest.Create(requestUrl);
request.Method = “POST”;

            using (var reqStream = request.GetRequestStream())
{
var postData = string.Format(@”client_id={0}&client_secret={1}&resource={2}&username={3}&password={4}&grant_type=password”,
clientId, clientSecret,url, userName, password);

var postBytes = Encoding.ASCII.GetBytes(postData);
reqStream.Write(postBytes, 0, postBytes.Length);
reqStream.Close();
}

            var accessToken = default(string);
using (var response = (HttpWebResponse)request.GetResponse())
{

var stream= response.GetResponseStream();
if (stream!= null)
{
var reader = new StreamReader(stream);
var json = reader.ReadToEnd();

              // Here I am using Newtonsoft.json

                    var dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
accessToken = (string)dict[“access_token”];

                }
}

            return accessToken;

        }

And delight is when you get the access token back. Now with the access token in your hand, you have the trump card. You can query Web API and what not.

Great isn’t it? To be honest with my readers, after this method without using ADAL worked out in my previous post, I just tried out sending the client secret in exactly the same way and it worked like a charm. Serendipity you can say!

Hope this helps.

Debajit Dutta

(Dynamics MVP)

For corporate training/ consulting please write to us at info@xrmforyou.com

Headless Authentication with Dynamics CRM online Web API – Without using ADAL {Part-I}

Well this topic has been discussed again over multiple times. And I myself has written a blog on how to do a headless authentication (without user intervention) between Dynamics CRM Online Web API and Native APP (console APP) – https://debajmecrm.com/2016/06/21/dynamics-crm-web-api-login-authentication-screen/

If you go through the above post, I have used ADAL (active directory authentication library) to query the authorization token and then use the authorization token to query the Dynamics CRM Web API. However there is a catch to this.

This headless authentication was only possible with Native APPs (console APPs) since they just required Client ID’s and does not require the Client Secret to actually generate the token. And hence I was not able to use this method to get the token from a Web Application which would require the Client_Secret.

And while I was doing a training session on this recently, I was asked the question. Is there really no way? Is ADAL absolutely necessary?

Well that sparked me. I decided to spend some time and dig deep. I tried to extend the AcquireToken method of ADAL but to no use. A lot of digging and finally came up with this.

This is Part-I of this blog. Here I will first show you how to get the token from D365 online from a Native App like C# console APP. In the next blog I will show you how we can extend this to use for client_secret as well.

My CRM URL – https://xrm4u1.crm.dynamics.com

I am not going into detail on how to register an APP in azure and give it access to Dynamics CRM. There are so many wonderful blogs which explains in detail. Below is the code to just obtain the token with using any external libraries (ADAL or anything)

public string GetCRMToken()
{

var azureTenantId= “xrm4u1.onmicrosoft.com”;
var clientId = “<client id of the console app after registering in azure>”;
var requestUrl = string.Format(@”
https://login.microsoftonline.com/{0}/oauth2/token”,
azureTenantId);

var url = “https://xrm4u1.crm.dynamics.com”;
            var userName = “<username>”;
var password = “<password>”;

            // Connect to the authentication server

            var request = (HttpWebRequest)WebRequest.Create(requestUrl);
request.Method = “POST”;


            using (var reqStream = request.GetRequestStream())
{
var postData = string.Format(@”client_id={0}&resource={1}&username={2}&password={3}&grant_type=password”,
clientId, url, userName, password);
var postBytes = Encoding.ASCII.GetBytes(postData);
reqStream.Write(postBytes, 0, postBytes.Length);
reqStream.Close();
}

 

            var accessToken = default(string);
using (var response = (HttpWebResponse)request.GetResponse())
{

var stream= response.GetResponseStream();
if (stream!= null)
{
var reader = new StreamReader(stream);
var json = reader.ReadToEnd();

              // Here I am using Newtonsoft.json

 

                    var dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
accessToken = (string)dict[“access_token”];

                  

                }
}

            return accessToken;

        }

 

Smooth isn’t it? No reference to ADAL. Just simple HttpWebRequest and response.

Hope you liked this.

In the next blog I will show you how to extend this to even include client secret and get the token even from a Web application, which so many has been longing for sometime now.

 

Debajit Dutta

(Dynamics MVP)

For corporate training/ consulting please write to us at info@xrmforyou.com

{Quick Tip} Certificate disappearing in IIS of CRM server even after successful import.

Before I proceed with the post. let me clear this out. There is nothing special about IIS server where CRM is installed. It applies to all IIS servers. However being a devotee of Dynamics for quite sometime now, can’t write any post without tagging CRM to it. Smile

So here I was working for a client with on-premise 2016 version. And their certificate is about to expire. They needed to generate a CSR for a SAN Certificate as wildcard certificates are not allowed by most of company policies.

So they used Open SSL to generate the CSR. For reader’s who might be interested in knowing how to generate SAN Certificate using Open SSL, https://geekflare.com/san-ssl-certificate/ provides a good example. And they got the certificate back from the Network team.

Now the D-day. They imported the certificate in Personal store and  also imported the certificate in IIS using ‘Complete Certificate Request’ option. All set and good.

But the moment they try to bind the certificate to dynamics CRM site, they could not find the certificate. Repeated this process. However the same behavior every time.

A bit of research and this is what comes up – “Certificate without private Key Information in it, cannot be binded to a IIS website.”

But how to do it?

When you generate a CSR request using Open SSL, the private key is output to a file. Usually the name is “Private.Key”, unless you specified something else.

So you have the private key and the certificate separately. But how to bind the certificate with the Private key?

Follow the below steps

  • Copy the Private Key file and the certificate to the Open SSL bin folder. Usually is it C:\OpenSSL-Win64 for 64 bit machines and C:\OpenSSL-Win32 for 32 bit machines
  • Open command prompt as administrator and navigate to the bin folder in the command prompt.
  • Run the below command

openssl pkcs12 -export -out certificate.pfx –inkey private.key -in certificate.crt –certfile

Here Certificate.pfx in the output certificate with the private key information and certificate.crt is the certificate you received from Network team.

Once the command completed successfully, you should be able to view Certificate.pfx in the bin folder.

Now all set and done. You will now just need to import this certificate to the IIS. But remember to use the “Import” option in the certificate window.

image

 

A rather off topic but hope it makes an interesting read.

 

Debajit Dutta

(Business Solutions MVP)

For corportate training/ consulting, please drop a note to info@xrmforyou.com or visit our website – www.xrmforyou.com