1

I'm using the Microsoft.Owin middleware to authenticate users against Azure AD when they visit my page.

App_Start > Startup.cs

using Owin;
using System.Configuration;
using System.Globalization;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using Microsoft.Owin.Extensions;

[assembly:OwinStartup(typeof(MyApp.App_Start.Startup))]
namespace MyApp.App_Start
{
    public class Startup
    {
        private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
        private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
        private static string tenant = ConfigurationManager.AppSettings["ida:Tenant"];
        private static string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"];

        string authority = string.Format(CultureInfo.InvariantCulture, aadInstance, tenant);

        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
        }

        public void ConfigureAuth(IAppBuilder app)
        {
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new CookieAuthenticationOptions() { });

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {
                    ClientId = clientId,
                    Authority = authority,
                    PostLogoutRedirectUri = postLogoutRedirectUri,
                    Notifications = new OpenIdConnectAuthenticationNotifications
                    {
                        AuthenticationFailed = (context) =>
                        {
                            context.HandleResponse();
                            context.Response.Redirect("/Error/message=" + context.Exception.Message);

                            return System.Threading.Tasks.Task.FromResult(0);
                        }
                    }
                });

            app.UseStageMarker(PipelineStage.Authenticate);
        }
    }
}

This is working fine, after they sign in I can use things like the ClaimsPrincipal to get information about this user such as their ID:

string signedInUserID
    = ClaimsPrincipal.Current.FindFirst(System.IdentityModel.Claims.ClaimTypes.NameIdentifier).Value;
string tenantID
    = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
string userObjectID
    = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;

I now want to silently authenticate against CRM Online as this user so I can pull data from the Web API. Is this possible, and if so, how?


I've been trying to follow the examples to acquire an access token via AuthenticationContext which I seem to get successfully, but then I'm unable to query CRM Online, I get various errors about security. For the sake of brevity I won't list all the code here unless someone specifically needs to see it. Here's the MSDN article that gives the basics.

I can access CRM Online using the CrmConnection class and a connection string with the username and password hard coded in as documented in this MSDN article but this isn't what I want. I want to authenticate as the currently logged in user.

Here are some of the samples I've been trying to follow in case they're useful to anyone else: https://github.com/azure-samples?query=active-directory

This is the closest post I've found to what I want but it still needs a username/password... Using ADAL C# as Confidential User /Daemon Server /Server-to-Server - 401 Unauthorized

Community
  • 1
  • 1
Equalsk
  • 7,954
  • 2
  • 41
  • 67
  • "I can access CRM Online using the CrmConnection class and a connection string with the username and password hard coded in as documented in this MSDN article but this isn't what I want. I want to authenticate as the currently logged in user." ---> OrganizationServiceProxy (http://stackoverflow.com/questions/37570224/crm-dynamics-2013-how-to-pass-current-logged-as-the-record-owner/37577406#37577406) – dynamicallyCRM Jul 28 '16 at 15:31
  • Unless I'm mistaken this doesn't apply to CRM Online, it's part of the Xrm.Client library which is not in the latest SDK as far as I can see. – Equalsk Jul 28 '16 at 15:50
  • The example you originally linked to requires `CrmConnection` class which is in `Microsoft.Xrm.Client` library and not `Microsoft.Xrm.Sdk.Client` library. Am I missing something? Edit: Oh, you deleted your comment... – Equalsk Jul 28 '16 at 16:00
  • Yes, I deleted my comment because I could not update it anymore, use 2015 SDK with 2016 SDK, I use 2016 SDK and 2015 SDK's Microsoft.Xrm.Client dll in conjunction. No issues. Apparently starting 2016 dlls are segregated into different namespaces --> Xrm.Tooling (https://msdn.microsoft.com/en-us/library/dn689057.aspx) . But my initial comment still stands, no 2 versions of CRM SDK for online and on-prem, looks like with 2016 they have just seggregated it into different namespaces. – dynamicallyCRM Jul 28 '16 at 16:02
  • Using Xrm.Tooling, code would be in the lines of : var client = new CrmServiceClient("Xrm"); client.OrganizationServiceProxy.CallerId = new Guid("GuidOfTheUserToPassAsTheCaller"); – dynamicallyCRM Jul 28 '16 at 16:17
  • Thanks, I'll see if I can pass the user GUID in this way and whether it will let me query the data. – Equalsk Jul 28 '16 at 16:22
  • I can't get this to work unless I use a username/password. All my reading suggests that CRM Online requires a username/password to generate a token successfully. If I supply these details everything works fine, every other method I've tried including specifying the caller ID does not work, I always receive a 401 unauthorized error. – Equalsk Aug 09 '16 at 16:20

1 Answers1

0

It seems that CRM Online doesn't support any kind of anonymous or passive authentication and must always be supplied with a valid username and password.

I've resorted to simply creating a user solely for API access and using these credentials to authenticate with CRM. Although this is not what I wanted it does work fine.

I'd love for someone to prove me wrong but it doesn't seem this is possible right now.

Equalsk
  • 7,954
  • 2
  • 41
  • 67
  • Is this still true as of today? I am experimenting with getting data from CRM online but reciving a 401 unauthorized although the user has been authorized before (but not by password, he was already logged in to o365 and has an access token). – Patric May 18 '20 at 06:44
  • @Patric I don't know if other methods have since become available, I've had no reason to check, but I can say that authenticating as a user still works solidly. – Equalsk May 18 '20 at 12:11