Category: WEB API

CRM Web Portal with Token Based authentication -Part 1

CRM Web Portal with Token Based authentication -Part 1

Sometime we have a requirement to make a web portal with using CRM as back end e.g. ticket management portal. A portal is a custom application that allows external users to access and edit data that is stored in Microsoft Dynamics CRM (a.k.a CRUD – Create, Read, Update and Delete operations). A CRM portal application can be developed with different technologies along with the Dynamics CRM Web Services for data access.

In this article we’ll discuss how we can implement token based authentication in CRM web portal.I’ll divided this article into two parts

  1. CRM Web Portal with JWT authentication -Part 1
  2. Intregate CRM web portal with AngularJS-Part 2(coming soon..)

Token Based Authentication

As I stated before we’ll use token based approach to implement authentication between the front-end application and the CRM API, as we all know the common and old way to implement authentication is the cookie-based approach were the cookie is sent with each request from the client to the server, and on the server it is used to identify the authenticated user.

1. Create a web application (webapi) project in visual studio with no authentication.

create_new_project

create_new_project1

create_new_project2

2.Remove Global.asax from our project and add owin starup class i.e. startup.cs

using System;
using Microsoft.Owin;
using Owin;
using Microsoft.Owin.Security.OAuth;
using Microsoft.Owin.Security;
using System.Web.Http;
using System.Web.Routing;
using System.Web.Mvc;
using System.Net.Http.Headers;
using Microsoft.AspNet.Identity.Owin;

[assembly: OwinStartup(typeof(MSCRMjwtAuth.Startup))]

namespace MSCRMjwtAuth
{
public class Startup
{

public void Configuration(IAppBuilder app)
{
HttpConfiguration httpconfig = new HttpConfiguration();
WebApiConfig.Register(httpconfig);
RouteConfig.RegisterRoutes(RouteTable.Routes);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
app.UseWebApi(httpconfig);
httpconfig.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue(“text/html”));

// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
}
}
}

3.After that install below nuget packages

Install-Package Microsoft.AspNet.WebApi.Owin

Install-Package Microsoft.Owin.Host.SystemWeb

Install-Package Microsoft.Owin.Security.OAuth

Install-Package Microsoft.AspNet.Identity.Owin

Install-Package Microsoft.CrmSdk.CoreAssemblies

In this blog we’re authenticating user with contact entity, emailaddress1 field as username and custom attribute am_password  for password and we also store password in encrypted format.

4.Create a new solution i.e. JWTaunthentication for all our schema customization.

create_solution

5. CRMHelper class

CRMhelper class contains functions that check user and password from our existing CRM contact records on behalf of input that user provided.

/// <summary>
/// This class contains all crm functions
/// </summary>
public class CRMHelper
{
//Variable
public IOrganizationService _orgService;

//CRM dynamics Connection
CrmConnection connection = CrmConnection.Parse(ConfigurationManager.ConnectionStrings[“CRMConnectionString”].ConnectionString);

public CRMHelper()
{
_orgService = new OrganizationService(connection);
}

/// <summary>
/// Login Function for parent
/// </summary>
/// <param name=”arry”>array of login id and password</param>
/// <returns>Datacollection of contact entity</returns>
public DataCollection<Entity> tryLogin(string[] arry)
{
try
{
QueryExpression parentQuery = new QueryExpression()
{
EntityName = “contact”,
ColumnSet = new ColumnSet(“firstname”, “lastname”),
Criteria =
{
Filters =
{
new FilterExpression(LogicalOperator.And)
{
Conditions={
new ConditionExpression(“emailaddress1”,ConditionOperator.Equal,arry[0].ToString()),
new ConditionExpression(“am_password”,ConditionOperator.Equal,StringCipher.Encrypt(arry[1].ToString()))
}
}
}
}
};
return _orgService.RetrieveMultiple(parentQuery).Entities;
}
catch (Exception ex)
{
throw;
}
}

/// <summary>
/// Get all Cases related to logged in user
/// </summary>
/// <param name=”customerid”>Contact Entity guid</param>
/// <returns>Datacollection of Incident Entity</returns>
public DataCollection<Entity> getCases(Guid customerid)
{
try
{
// Instantiate QueryExpression QEincident
var QEincident = new QueryExpression(“incident”);

// Add columns to QEincident.ColumnSet
QEincident.ColumnSet.AddColumns(“title”);

// Define filter QEincident.Criteria
QEincident.Criteria.AddCondition(“customerid”, ConditionOperator.Equal, customerid);
return _orgService.RetrieveMultiple(QEincident).Entities;
}
catch (Exception ex)
{

throw;
}
}

}

5. OAuth Bearer Tokens Generation

Add a new class i.e. ApplicationOAuthProvider.cs in our web application that support for OAuth Bearer Tokens Generation.

public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
}

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
CRMHelper helper = new CRMHelper();
if (context.UserName != null && context.Password != null)
{
var collection = helper.tryLogin(new string[] { context.UserName, context.Password });
if (collection.Count > 0)
{
context.OwinContext.Response.Headers.Add(“Access-Control-Allow-Origin”, new[] { “*” });
var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
oAuthIdentity.AddClaim(new Claim(ClaimTypes.Email, context.UserName));
var ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties());
context.Validated(ticket);
}

}
//return base.GrantClientCredentials(context);
}
}

6. Encryption and Decryption class

public static class StringCipher
{
// This constant string is used as a “salt” value for the PasswordDeriveBytes function calls.
// This size of the IV (in bytes) must = (keysize / 8). Default keysize is 256, so the IV must be
// 32 bytes long. Using a 16 character string here gives us 32 bytes when converted to a byte array.
private static readonly byte[] initVectorBytes = Encoding.ASCII.GetBytes(“tu89geji340t89u2”);

// This constant is used to determine the keysize of the encryption algorithm.
private const int keysize = 256;
private const string passPhrase = “contact”;
public static string Encrypt(string plainText)
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
using (PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null))
{
byte[] keyBytes = password.GetBytes(keysize / 8);
using (RijndaelManaged symmetricKey = new RijndaelManaged())
{
symmetricKey.Mode = CipherMode.CBC;
using (ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes))
{
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
return Convert.ToBase64String(cipherTextBytes);
}
}
}
}
}
}

public static string Decrypt(string cipherText)
{
byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
using (PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null))
{
byte[] keyBytes = password.GetBytes(keysize / 8);
using (RijndaelManaged symmetricKey = new RijndaelManaged())
{
symmetricKey.Mode = CipherMode.CBC;
using (ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes))
{
using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
}
}
}
}
}
}

7. Create CRM contact record

Also create a record for contact entity in CRM with amankothari@outlook.com as Email and ChHTqB6783q4J/b5BHD7vQ==  as Password (we stored password in encrypted form).

ContactForm.png

8. Add secured controller for Incident

[RoutePrefix(“api/cases”)]
public class CasesController : ApiController
{
CRMHelper helper = new CRMHelper();
[Authorize]
[HttpGet]
[Route(“”)]
public DataCollection<Entity> Getcases()
{
try
{
var identity = (ClaimsIdentity)User.Identity;
foreach (var a in identity.Claims)
{
if (a.Type == “contactid”)
{
return helper.getCases(new Guid(a.Value));
}}
return null;

}
catch (Exception ex)
{
return null;
}
}
}

Notice how we added the “Authorize” attribute on the method “Get” so if you tried to issue HTTP GET request to the end point “http://localhost:port/api/cases&#8221; you will receive HTTP status code 401 unauthorized because the request you send till this moment doesn’t contain valid authorization header.

9.Modified our startup.cs code for support for OAuth Bearer Tokens.

using System;
using Microsoft.Owin;
using Owin;
using Microsoft.Owin.Security.OAuth;
using Microsoft.Owin.Security;
using System.Web.Http;
using System.Web.Routing;
using System.Web.Mvc;
using System.Net.Http.Headers;
using Microsoft.AspNet.Identity.Owin;

[assembly: OwinStartup(typeof(MSCRMjwtAuth.Startup))]

namespace MSCRMjwtAuth
{
public class Startup
{
public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
public void Configuration(IAppBuilder app)
{
HttpConfiguration httpconfig = new HttpConfiguration();
ConfigureOAuth(app);
WebApiConfig.Register(httpconfig);
RouteConfig.RegisterRoutes(RouteTable.Routes);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
app.UseWebApi(httpconfig);
httpconfig.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue(“text/html”));

// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
}
public void ConfigureOAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString(“/oauth/token”),
Provider = new ApplicationOAuthProvider(),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
AllowInsecureHttp = true,
};

// Token Generation
app.UseOAuthBearerTokens(OAuthOptions);
}
}
}

Assuming that you saved the username “amankothari@outlook.com”  with password “ChHTqB6783q4J/b5BHD7vQ==” (123456) in CRM. In the step below, we’ll use the same username to generate token, so to test this out open your favorite REST client application in order to issue HTTP requests to generate token for user “amankothari@outlook.com”. For me I’ll be using PostMan.

Now we’ll issue a POST request to the endpoint http://localhost:57205/oauth/token the request will be as the image below:

Postman1.PNG

If the username and password are not same then we sent bad request in response.

invalid_token_postman

If all is correct we’ll receive HTTP status 200 along with the secured data in the response body, if you try to change any character with signed token you directly receive HTTP status code 401 unauthorized.

Casescaseresponse

Now our back-end API is ready to be consumed from any front end application or native mobile app.

In my next blog we’ll consumed this API with angularJS application.

Below are the links of solution and web project code respectively.

https://1drv.ms/u/s!AvWbcg6Nl97LiUsVexaWI0gZV2TP

https://1drv.ms/u/s!AvWbcg6Nl97LiUyciNWPn4ehGpNH

 

 

 

 

 

Advertisements
What’s new in CRM dynamics for developers

What’s new in CRM dynamics for developers

Hi fellas this is my first blog and i am really excited about it.Today i am gonna tell you about what is new in CRM dynamics 2016.

1.CRM Online features now available for on-premises organizations

New features that were added to Microsoft Dynamics CRM Online 2015 Update 1 are now available for on-premises organizations. One exception is the integration with Parature which is only available for CRM Online. For a summary of new features included in that release, see What’s new for Microsoft Dynamics CRM Online 2015 Update 1

2.Web API

The Web API will make it easier to create applications across a wide variety of platforms, devices, and programming languages. The Web API provides parity with the existing organization service (SOAP endpoint). You will be able to do anything using the Web API that you can do using the organization service, with a few differences. You won’t have to download any Microsoft Dynamics CRM SDK assemblies. You can perform all operations using HTTP requests with the Web API located at [organization uri]/api/data/v8.0/.

for more info please visit at https://msdn.microsoft.com/en-us/library/gg309589.aspx#BKMK_WebAPI

webapi1

Discovery service

To maintain parity with the Discovery service on the SOAP endpoint, they’ve added a Discovery service to the Web API. This service enables you to determine, at run-time, the organizations that the signed-in user belongs to. You can retrieve information about those organizations like the organization service URL, the CRM release version, and more. A new feature of the Web API Discovery service is the ability to filter the returned list of organizations by using OData filter parameters. The Discovery service is supported by all CRM deployment types. More information: Discover the URL for your organization using the Web API

webapi1

Form script support for keypress events and auto-completion feature

Use the new getValue method to retrieve the value of a control when the user presses keys in a number or text control. You can use this value to configure interactive experiences, such as data validation as user types in a field, by configuring function handlers for keypress events using the newKeypress methods. In addition, you can use the new Auto-completion methods to configure the auto-completion feature for text controls in forms. These new methods aren’t supported for CRM for phones or CRM for tablets.

For more Info please visit at
https://msdn.microsoft.com/en-us/library/mt607648.aspx

Web resources and IFRAMEs

The ability to create web resources and IFRAMEs for use with CRM for tablets is now fully supported in all CRM for tablets forms: iOS, Android, and Windows 10. Previously, this was only available as a preview feature. More information:Create web resources and IFrame content for use with the CRM for tablets client

Form script support for new custom controls

Use new custom controls to configure a visually modern and richer experience for your users in CRM for phones and CRM for tablets. More information:TechNet: Use the form editor

The new custom controls support all the existing client APIs supported by the CRM controls, except for the Auto-completion methods, getValue,Keypress methods and Lookup control methods and events. For the complete list of client APIs supported by CRM controls, see Xrm.Page.ui control (client-side reference).

Open records in CRM mobile client with a URL

The new application handler protocol in Microsoft Dynamics CRM 2016 enables you to use URLs to directly open records in CRM for phones and CRM for tablets. It also lets you open an empty form for creating an entity record. To use this feature, you have to install the CRM for phones or CRM for tablets application on your mobile device. More information: Open forms, views, and dashboards in CRM mobile client with a URL

Knowledge management enhancements

The CRM Service module gets a boost in this release with the addition of powerful knowledge management capabilities. In addition to rich text, the newKnowledgeArticle entity supports multimedia data like pictures and videos. Articles have a lifecycle where they proceed through a publishing workflow.

Discover the answers to your questions using full text searches of knowledge base records for topics and products using theFullTextSearchKnowledgeArticleRequest message. This message provides systematic access to a keyword based search index of the article content. Use this message to access that search content and provide search results to customers and partners.

To support the knowledge management capability, new privileges named Publish Knowledge Articles and Approve Knowledge Articles were added. The Customer Service Representative and Customer Service Manager roles have these privileges, and a new Knowledge Manager role has been added.

For the CRM web client, the client-side form programming API has been updated to include additional properties in the object returned from thegetSelectedResult function call. All other client APIs and events, which were supported by the knowledge base search control in the Microsoft Dynamics CRM 2015 release, continue to be supported.

For the new interactive service hub client, only the getSearchQuery and setSearchQuery methods are supported for the knowledge base search control.

For more information about the client-side APIs supported by knowledge base search control, see Knowledge base search control (client-side reference). For more information about knowledge management, see Knowledge management entities.

Solution enhancements

Previously, when an entity was added to a solution and that solution was exported, the entity and all of its assets were exported in that solution. This included attributes, forms, views, relationships, visualizations, and any other assets packaged with the entity. All objects were exported regardless of whether the developer actually wanted to ship the object. This process potentially carried dependencies or modified unintended objects on the target deployment.

A new solution capability is now available that allows a developer or other application customizer to create solution patches that contain subcomponents of entities, as compared to publishing the entire entity and all of its assets. The original solution and multiple released patches can be rolled-up at a later time into an updated version of the original solution, which then can replace the original solution.

solution

Upload and manage document templates

You can now create document templates (Microsoft Excel or Microsoft Word) to have a standardized representation of your CRM data. These templates can be used by your team members to generate Excel or Word documents with up-to-date CRM data for analysis and reporting purposes. Use the SDK to programmatically upload and manage document templates.

More information: Upload and manage document templates in CRM

XRM Tooling controls now support OAuth authentication and connection strings

Microsoft.Xrm.Tooling.Connector is the primary interface to CRM for all tooling and Unified Service Desk operations. It is also provided as part of the Microsoft Dynamics CRM SDK to developers who want to build CRM connected Windows applications. Developers can use this updated API to allow the OAuth 2 protocol to be used to authenticate with CRM web services. Adding OAuth enables multi-factor authentication for improved security and access to CRM.

XRM tooling now also supports connection strings, which allow for the use of SQL-like connection strings in the CrmServiceClient class.

More information: Build Windows client applications using the XRM tools

New entities in CRM 2016

The following table lists new entities included in this release.

Schema name Display name Description
KnowledgeArticle Knowledge Article Describes articles that are organizational knowledge for internal and external use. More information:Work with knowledge articles in Dynamics CRM
KnowledgeArticleIncident Knowledge Article Incident Contains the associations between a knowledge article and incident. More information: Work with knowledge articles in Dynamics CRM
KnowledgeArticleViews Knowledge Article Views Tracks the number of times an article is viewed per day. More information: Work with knowledge articles in Dynamics CRM
LanguageLocale Language Contains information about the supported languages for translating a knowledge article. More information: Work with knowledge articles in Dynamics CRM

New messages in CRM 2016

The following table lists new messages included in this release.

Request class name Web API action Description More information
CloneAsPatchRequest CloneAsPatch Action Creates a solution patch from a managed or unmanaged solution. Create patches to simplify solution updates
CloneAsSolutionRequest CloneAsSolution Action Creates a new copy of an unmanaged solution that contains the original solution plus all of its patches. Create patches to simplify solution updates
CreateKnowledgeArticleTranslationRequest CreateKnowledgeArticleTranslation Action Creates a translation of a knowledge article record. Create a knowledge article translation
CreateKnowledgeArticleVersionRequest CreateKnowledgeArticleVersion Action Creates a major or minor version of a knowledge article record. Create major and minor versions of a knowledge article
DeleteAndPromoteRequest DeleteAndPromote Action Replaces a managed solution plus all of its patches. Create patches to simplify solution updates
FullTextSearchKnowledgeArticleRequest N/A Performs a full-text search on knowledge articles in CRM using the specified search text. Search knowledge articles using full-text search
IncrementKnowledgeArticleViewCountRequest N/A Increments the per day view count of a knowledge article record. Increment knowledge article view count
SetProcessRequest SetProcess Action Sets the process that associates with a given target entity.
UpdateSolutionComponentRequest UpdateSolutionComponent Action Updates a component in an unmanaged solution. Package and distribute extensions using solutions

for more info visit at

https://msdn.microsoft.com/en-us/library/gg309589.aspx

 

Software Development Kit for Microsoft Dynamics CRM Online and CRM 2016 (on-premises)

https://msdn.microsoft.com/en-us/library/hh547453.aspx