Keep getting "The payload was invalid" exception from ProtectedBrowserStorage - c#

In my .NET 5 Blazor Server Application I add dataprotection to my services using the following line in my Program.cs
builder.Services.AddDataProtection()
.SetApplicationName("WhateverApplicationName")
.PersistKeysToDbContext<KpaContext>();
Now when I try to get data from ProtectedLocalStorage using this code
try
{
var sessionid = await ProtectedLocalStorage.GetAsync<Guid>("BrowserId");
}
catch(Exception ex)
{
Debugger.Break();
}
It keeps throwing this error:
System.Security.Cryptography.CryptographicException: The payload was
invalid.
at
Microsoft.AspNetCore.DataProtection.Managed.ManagedAuthenticatedEncryptor.Decrypt(ArraySegment1 protectedPayload, ArraySegment1 additionalAuthenticatedData) at
Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.UnprotectCore(Byte[]
protectedData, Boolean allowOperationsOnRevokedKeys, UnprotectStatus&
status) at
Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Unprotect(Byte[]
protectedData) at
Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.Unprotect(IDataProtector
protector, String protectedData) at
Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage.ProtectedBrowserStorage.GetAsync[TValue](String
purpose, String key)
The application runs on a docker container.
The table DataProtectionKeys contains a record of a key which is valid from 05-07 till 03-10 so the key should be active.
What am I doing wrong. I used this link to configure data protection:
https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-6.0

Related

Smart home report state SYNC new device | Requested entity was not found. [404]

I've implemented the HomeGraph API with the help of the package Google.Apis.HomeGraphService.v1 (1.50.0.2260)
It seems to work fine as well, the ReportStateAndNotification function works fine on the query, execute, and some sync requests.
But when I add a new device to my system through our app and a SYNC request is sent to Google and comes in our backend, the HomeGraph API will return an exception when sending this sync request..
-> The sync request does not throw an exception when I modify a device name in our app. It only occurs when new devices are added.
I've searched through google and multiple StackOverflow posts.. But I'm probably missing something. Most posts say check the API key etc but then the ReportStateAndNotification function should always fail, not only when the sync request comes from Google to our backend.
Could anyone point me in the right direction?
Function that is used for sync requests:
public static void Send(Dictionary<string, object> deviceStateList, string requestId, string googleCustomerId)
{
string deviceIdList = String.Format("({0})", string.Join(", ", deviceStateList.Keys));
try
{
var jsonFilePath = _appSettingsRetriever.PrivateGoogleAuthenticationFile;
string scope = "https://www.googleapis.com/auth/homegraph";
using (var stream = new FileStream(jsonFilePath, FileMode.Open, FileAccess.Read))
{
GoogleCredential credentials = GoogleCredential.FromStream(stream);
if (credentials.IsCreateScopedRequired)
credentials = credentials.CreateScoped(scope);
HomeGraphServiceService service = new HomeGraphServiceService(new BaseClientService.Initializer()
{
HttpClientInitializer = credentials
});
var request = new ReportStateAndNotificationRequest
{
AgentUserId = googleCustomerId,
RequestId = requestId,
Payload = new StateAndNotificationPayload
{
Devices = new ReportStateAndNotificationDevice
{
States = deviceStateList
}
}
};
_log.Debug($"Sending to HomeGraph for devices: {deviceIdList} customer: {googleCustomerId} requestId: {requestId}");
DevicesResource.ReportStateAndNotificationRequest rp = service.Devices.ReportStateAndNotification(request);
ReportStateAndNotificationResponse resop = rp.Execute();
}
}
catch (Exception ex)
{
_log.Error($"Exception in ReportToHomeGraph for Customer: {googleCustomerId}. DeviceList: {deviceIdList}. JsonPath: {_appSettingsRetriever.PrivateGoogleAuthenticationFile} Exception: {ex}.");
}
}
Exception:
2021-09-24 14:16:13,547 [110] ERROR ReportToHomeGraph
Exception in ReportToHomeGraph for Customer: 05. DeviceList: (
fe965e6a-21ad-425f-b594-914bf63510a9,
1cc0ee97-a87f-44c5-a3e3-a39d159ee193,
618cdf94-2b31-434f-b91e-00837d155d4a
).
JsonPath: C:/myfile.json Exception: The service homegraph has thrown an exception:
Google.GoogleApiException: Google.Apis.Requests.RequestError
Requested entity was not found. [404]
Errors [
Message[Requested entity was not found.] Location[ - ] Reason[notFound] Domain[global]
]
at Google.Apis.Requests.ClientServiceRequest`1.<ParseResponse>d__35.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Google.Apis.Requests.ClientServiceRequest`1.Execute()
at BusinessLogic.GoogleAssistant.TokenService.HomeGraph.ReportToHomeGraph.Send(Dictionary`2 deviceStateList,
String requestId, String googleCustomerId) in C:\Repos\GoogleAssistant
.TokenService\HomeGraph\ReportToHomeGraph.cs:line 57.
When users add a new device, the first step you need to do is to issue a Request Sync to Google. This indicates the set of devices for that user has changed, and you need a new Sync request to update the data in homegraph. Google will follow this by delivering a Sync intent to your fulfillment endpoint, which you can respond with the updated set of devices.
Getting a 404 when calling Request Sync might indicate your Service Account Key might be invalid, or the agent user id you target might be wrong. Otherwise getting an error for your Sync Response might indicate it’s structured incorrectly. You can find out more about how to structure it in our examples.

Couchbase error opening bucket - Could not bootstrap

I am trying to connect to my couchbase server (Enterprise ver 4.6.2) and open a bucket using the .Net SDK, the code is very simple but still fail to work:
var cluster = new Cluster(new ClientConfiguration
{
Servers = new List<Uri> { new Uri("https://10.0.0.54:8091/") }
});
try
{
var bucket = cluster.OpenBucket("default");
}
catch (Exception ex)
{
Console.WriteLine("Error getting bucket.");
Console.WriteLine(ex.Message);
}
The inner exception details I get:
Message
Object reference not set to an instance of an object
StackTrace
Couchbase.IO.Services.PooledIOService.CheckEnabledServerFeatures(IConnection connection)
at Couchbase.IO.Services.PooledIOService..ctor(IConnectionPool connectionPool)
at Couchbase.IO.IOServiceFactory.<>c__DisplayClass0_0.<GetFactory>b__0(IConnectionPool pool)
at Couchbase.Configuration.Server.Providers.CarrierPublication.CarrierPublicationProvider.GetConfig(String bucketName, String username, String password)
The main exception I see is:
Could not bootstrap - check inner exceptions for details.
And the stack trace:
at Couchbase.Core.ClusterController.CreateBucket(String bucketName, String username, String password, IAuthenticator authenticator)
at Couchbase.Core.ClusterController.CreateBucket(String bucketName, IAuthenticator authenticator)
at Couchbase.Cluster.OpenBucket(String bucketname)
at Couchbase.Program.Main(String[] args)
Any idea what the issue is?
I had the same problem with the Community edition. In my case I had not created the default bucket before trying to access it. Also, if your server/cluster or bucket require credentials you need to enter those as well.
Expose all required ports
docker run -d -p 8091-8096:8091-8096 -p 11210:11210 -p 11211:11211 couchbase

CryptographicException in StateDataFormat.Unprotect()

I recently posted a question which has been answered but led to this new problem. If interested, it can be seen at Previous post.
Intro
I am currently developing an application using AD-B2C as my identity provider. This is integrated into the solution using their guidelines at AD B2C graph, which uses openid-connect.
I need to use a form of email activation (outside of their register policy) and as such I need to be able to pass a value from the URL in the email, through the sign-up process at B2C and back to the redirection URL.
For this we use the state parameter.
Problem
In my OnRedirectToIdentityProvider I encrypt the state
private Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
var temp = notification.ProtocolMessage.State;
// To be used later
var mycustomparameter = notification.OwinContext.Get<string>("mycustomparameter");
if (notification.ProtocolMessage.State != null)
{
var stateQueryString = notification.ProtocolMessage.State.Split('=');
var protectedState = stateQueryString[1];
var state = notification.Options.StateDataFormat.Unprotect(protectedState);
state.Dictionary.Add("mycustomparameter", "testing");
notification.ProtocolMessage.State = stateQueryString[0] + "=" + notification.Options.StateDataFormat.Protect(state);
}
return Task.FromResult(0);
}
This works for all I can tell.
Now the user is passed to the sign in on the AD B2C and is after the login redirected back where the OnMessageReceived is triggered.
private Task OnMessageReceived(MessageReceivedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
string mycustomparameter;
var protectedState = notification.ProtocolMessage.State.Split('=')[1];
var state = notification.Options.StateDataFormat.Unprotect(protectedState);
state.Dictionary.TryGetValue("mycustomparameter", out mycustomparameter);
return Task.FromResult(0);
}
this is where it breaks. In the ...StateDataFormat.Unprotect(protectedState)
It throws an error System.Security.Cryptography.CryptographicException with the message "Error occurred during a cryptographic operation."
EDIT: Stacktrace:
System.Web.dll!System.Web.Security.Cryptography.HomogenizingCryptoServiceWrapper.HomogenizeErrors(System.Func<byte[], byte[]> func, byte[] input) Unknown
System.Web.dll!System.Web.Security.Cryptography.HomogenizingCryptoServiceWrapper.Unprotect(byte[] protectedData) Unknown
System.Web.dll!System.Web.Security.MachineKey.Unprotect(System.Web.Security.Cryptography.ICryptoServiceProvider cryptoServiceProvider, byte[] protectedData, string[] purposes) Unknown
System.Web.dll!System.Web.Security.MachineKey.Unprotect(byte[] protectedData, string[] purposes) Unknown
Microsoft.Owin.Host.SystemWeb.dll!Microsoft.Owin.Host.SystemWeb.DataProtection.MachineKeyDataProtector.Unprotect(byte[] protectedData) Unknown
Microsoft.Owin.Security.dll!Microsoft.Owin.Security.DataProtection.AppBuilderExtensions.CallDataProtectionProvider.CallDataProtection.Unprotect(byte[] protectedData) Unknown
Microsoft.Owin.Security.dll!Microsoft.Owin.Security.DataHandler.SecureDataFormat<Microsoft.Owin.Security.AuthenticationProperties>.Unprotect(string protectedText) Unknown
IntellifyPortal.dll!IntellifyPortal.Startup.OnMessageReceived(Microsoft.Owin.Security.Notifications.MessageReceivedNotification notification) Line 171 C#
My attempts
I have tried specifying machine keys in the Web.config
I have tried messing with the "CallbackPath property in OpenIdConnectAuthenticationOptions, with no success.
I have tried a lot of diffent tweaks, but I can't seem to figure out why I can't "unprotect" the inbound state.
Any help is appreciated,
Best regards.
Update: Solution
I have decided to use an alternative method, which I found to work(hopefully it may of use to others):
Azure-sample which I used as guidance
private Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
var policy = notification.OwinContext.Get<string>("Policy");
if (!string.IsNullOrEmpty(policy) && !policy.Equals(DefaultPolicy))
{
notification.ProtocolMessage.Scope = OpenIdConnectScopes.OpenId;
notification.ProtocolMessage.ResponseType = OpenIdConnectResponseTypes.IdToken;
notification.ProtocolMessage.IssuerAddress = notification.ProtocolMessage.IssuerAddress.ToLower().Replace(DefaultPolicy.ToLower(), policy.ToLower());
}
// Accept Invitation Email
string testValue= notification.OwinContext.Get<string>("testValue");
string testValue2= notification.OwinContext.Get<string>("testValue2");
if (!string.IsNullOrEmpty(testValue) && !string.IsNullOrEmpty(testValue2))
{
var stateQueryString = notification.ProtocolMessage.State.Split('=');
var protectedState = stateQueryString[1];
var state = notification.Options.StateDataFormat.Unprotect(protectedState);
state.Dictionary.Add("testValue", testValue);
state.Dictionary.Add("testValue2", testValue2);
notification.ProtocolMessage.State = stateQueryString[0] + "=" + notification.Options.StateDataFormat.Protect(state);
}
return Task.FromResult(0);
}
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification notification)
{
// Extract the code from the response notification
var code = notification.Code;
string signedInUserID = notification.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
TokenCache userTokenCache = new MSALSessionCache(signedInUserID, notification.OwinContext.Environment["System.Web.HttpContextBase"] as HttpContextBase).GetMsalCacheInstance();
ConfidentialClientApplication cca = new ConfidentialClientApplication(ClientId, Authority, RedirectUri, new ClientCredential(ClientSecret), userTokenCache, null);
try
{
AuthenticationResult result = await cca.AcquireTokenByAuthorizationCodeAsync(code, Scopes);
// Look for acceptInvitation
string testValue;
string testValue2;
var protectedState = notification.ProtocolMessage.State.Split('=')[1];
var state = notification.Options.StateDataFormat.Unprotect(protectedState);
state.Dictionary.TryGetValue("testValue", out testValue);
state.Dictionary.TryGetValue("testValue2", out testValue2);
// InvitationAccept / store values
if(!string.IsNullOrEmpty(testValue) && !string.IsNullOrEmpty(testValue2))
{
// How can I pass values to the redirect controller?
// Can I somehow transfer it from here to that destination
}
}
catch (Exception ex)
{
//TODO: Handle
throw;
}
}
Final Question
I can now receive the values back as expected. These values has to be used in creating a relation between the new account and other accounts/groups in the application.
I therefore want to transfer these values back to the application (controller) for processing. I've tried storing the values in the context, in the response headers and in the claims to no avail. I guess this is because that this is the "middleware" and that the actual "redirect" happens directly from AD B2C thus not holding my params.
Can I somehow get the params back to the controller as well, without relying on the request URI (originating from the original user link) - Preferably directly in the claims, so that a user already logged in does not have to "re-signin" upon clicking the link.
How can I get my values (in the state, which are handled in the OnMessageRecieved) passed to the controller which is redirected to?
You're not supposed to decrypt the hint. Instead of this:
ProtocolMessage.State.Split('
Remove the hint so you only have encrypted data:
ProtocolMessage.State.Parameters["state"].Replace("OpenId.AuthenticationOptions=","")
Then you can you decrypt value of sate:
StateDataFormat.Unprotect("TC%$t43tj9358utj3")
It should deserialize to AuthenticationOptions.

Write a caught ASP.NET exception to EventLog without losing detail

This article explains in detail how to log an ASP.NET exception to the Windows EventLog and display a custom error page to the end-user.
However, the standard Event Logging mechanism for an ASP.NET web application automatically includes a lot of useful information not shown in this article. Implementing the code in the article results in a loss of detail/granularity in my error Event.
For example with automatic uncaught exception logging, you can see many attributes under the headings: Event Information, Application Information, Process Information, Request Information, Thread Information, Custom Event Details.
How can I implement logging of all of the same information that is logged in an uncaught exception and append my custom information into the section Custom Event Details? The best answer should preferably use some inbuilt method(s) of System.Diagnostics or System.Exception or similar i.e. writing as little code as possible to write the log entry with all sections mentioned above and simply append any custom details to the string.
If it is possible, I would also like to return the unique hashed Event ID (example b68b3934cbb0427e9497de40663c5225 from below) back to the application for display on my ErrorPage.aspx
Example of log format required:
Event code: 3005
Event message: An unhandled exception has occurred.
Event time: 15/07/2016 15:44:01
Event time (UTC): 15/07/2016 14:44:01
Event ID: b68b3934cbb0427e9497de40663c5225
Event sequence: 131
Event occurrence: 2
Event detail code: 0
Application information:
Application domain: /LM/W3SVC/3/ROOT-1-131130657267252632
Trust level: Full
Application Virtual Path: /
Application Path: C:\WWW\nobulus\nobulusPMM\Application\PMM\
Machine name: L-ADAM
Process information:
Process ID: 47216
Process name: iisexpress.exe
Account name: L-ADAM\Adam
Exception information:
Exception type: ApplicationException
Exception message: Error running stored procedure saveValidation: Procedure or function 'saveValidation' expects parameter '#ValidatedBy', which was not supplied.
at PMM.Models.PMM_DB.runStoredProcedure(String StoredProcedureName, List`1 SQLParameters) in C:\WWW\nobulus\nobulusPMM\Application\PMM\Models\PMM_DB.cs:line 104
at PMM.Models.PMM_DB.saveValidation(String PTLUniqueID, String ValidatedBy, DateTime ValidationDateTime, Nullable`1 ValidationCategoryID, String ValidationCategory, String Comment, Nullable`1 ClockStartDate, Nullable`1 ClockStopDate, String StartRTTStatus, String StopRTTStatus, String LastRTTStatus, Boolean MergedPathway, String MergedPathwayID, String ExtinctPathwayID, DataTable ChecklistResponses) in C:\WWW\nobulus\nobulusPMM\Application\PMM\Models\PMM_DB.cs:line 265
at PMM.Validate.lnkSaveButton_Click(Object sender, EventArgs e) in C:\WWW\nobulus\nobulusPMM\Application\PMM\Validate.aspx.cs:line 323
at System.Web.UI.WebControls.LinkButton.OnClick(EventArgs e)
at System.Web.UI.WebControls.LinkButton.RaisePostBackEvent(String eventArgument)
at System.Web.UI.WebControls.LinkButton.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
Request information:
Request URL: http://localhost:6901/Validate?PTLUniqueID=RTT10487
Request path: /Validate
User host address: ::1
User: L-ADAM\Adam
Is authenticated: True
Authentication Type: Negotiate
Thread account name: L-ADAM\Adam
Thread information:
Thread ID: 19
Thread account name: L-ADAM\Adam
Is impersonating: False
Stack trace: at PMM.Models.PMM_DB.runStoredProcedure(String StoredProcedureName, List`1 SQLParameters) in C:\WWW\nobulus\nobulusPMM\Application\PMM\Models\PMM_DB. cs:line 104
at PMM.Models.PMM_DB.saveValidation(String PTLUniqueID, String ValidatedBy, DateTime ValidationDateTime, Nullable`1 ValidationCategoryID, String ValidationCategory, String Comment, Nullable`1 ClockStartDate, Nullable`1 ClockStopDate, String StartRTTStatus, String StopRTTStatus, String LastRTTStatus, Boolean MergedPathway, String MergedPathwayID, String ExtinctPathwayID, DataTable ChecklistResponses) in C:\WWW\nobulus\nobulusPMM\Application\PMM\Models\PMM_DB.cs:line 265
at PMM.Validate.lnkSaveButton_Click(Object sender, EventArgs e) in C:\WWW\nobulus\nobulusPMM\Application\PMM\Validate.aspx.cs:line 323
at System.Web.UI.WebControls.LinkButton.OnClick(EventArgs e)
at System.Web.UI.WebControls.LinkButton.RaisePostBackEvent(String eventArgument)
at System.Web.UI.WebControls.LinkButton.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
Custom event details:
UPDATE
I actually found out using ILSpy and roaming in different framework classes that ASP.NET uses internally WebErrorEvent, which possess protected methods to achieve the same behavior.
Solution 1:
For that, just create a class which inherits WebErrorEvent, and then override its constructor:
public class CustomWebErrorEvent : WebErrorEvent
{
public CustomWebErrorEvent(string message, EventSource source, int eventCode, Exception ex) : base(message, source, eventCode, ex)
{
}
}
Then using it inside the Error management method from Global.asax:
protected void Application_Error(Object sender, EventArgs e)
{
// Log error to the Event Log
Exception myError = null;
if (HttpContext.Current.Server.GetLastError() != null)
{
var r = new CustomWebErrorEvent("error", null, 120, HttpContext.Current.Server.GetLastError());
}
}
I am pretty sure it is posslbe also to overload ASPNET to only raise straight a custom WebErrorEvent, but I didn't find it yet.
I am still trying to figure out how to add custom info to the event as overriding the method FormatCustomEventDetails is not getting called for Web Managed error events.
Solution 2:
If not possible as missing adding custom fields for now, you can use a similar method that I wrote which does the same output:
// Log error to the Event Log
Exception myError = null;
if (HttpContext.Current.Server.GetLastError() != null)
{
var request = HttpContext.Current.Request;
myError = HttpContext.Current.Server.GetLastError();
var dateAsBytes = System.Text.Encoding.UTF8.GetBytes(DateTime.Now.ToString("G"));
var id = Convert.ToBase64String(System.Security.Cryptography.MD5.Create().ComputeHash(dateAsBytes));
// Event info:
var eventMessage = myError.Message;
var currentTime = DateTime.Now.ToString("G");
var currentTimeUTC = DateTime.UtcNow.ToString("G");
// Application info:
var appDomainName = AppDomain.CurrentDomain.FriendlyName;
var appDomainTrustLevel = (AppDomain.CurrentDomain.IsFullyTrusted) ? "Full" : "Partial";
var appVirtualPath = VirtualPathUtility.GetDirectory(request.Path);
var appPath = request.PhysicalApplicationPath;
var machineName = Environment.MachineName;
// Process info:
var process = Process.GetCurrentProcess();
var processId = process.Id;
var processName = process.ProcessName;
var user = System.Security.Principal.WindowsIdentity.GetCurrent().User;
var accountName = user.Translate(typeof(System.Security.Principal.NTAccount));
// Exception info:
var exceptionType = myError.GetType().FullName;
var exceptionMessage = myError.Message;
var exceptionStack = myError.StackTrace;
// Request info:
var url = request.Url.AbsoluteUri;
var urlPath = request.Url.PathAndQuery;
var remoteAddress = request.UserHostAddress;
var userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
var isAuthenticated = HttpContext.Current.User.Identity.IsAuthenticated;
var authenticationType = System.Security.Principal.WindowsIdentity.GetCurrent().AuthenticationType;
// Thread info:
var impersonationLevel = System.Security.Principal.WindowsIdentity.GetCurrent().ImpersonationLevel;
var exceptionStack2 = myError.StackTrace;
// TODO: aggregate all info as string before writting to EventLog.
}
I found using existing .NET Apis almost all required fields from your output, just needed know to be aggregated as a string before outputting it in EventLog.
You can see that some of the object I am using (such as AppDomain.CurrentDomain, HttpContext.Current.Request or Process.GetCurrentProcess() returns a lot of other info, which could also ne added to the output if needed.
This all can be wrapped up under a method for code brevity of course.

OData from .Net application ends with Unauthorized

I am trying to consume the new Dynamics AX OData endpoint from a .Net console applications, I can see that the authentication is going fine but whenever I try to get the results on my application it ends with an Unauthorized error.
Any idea on what could be the cause or hos to get a more detailed information (logs)?
This is the code that throws the error at line:
foreach (var legalEntity in context.Teams.AsEnumerable())
static void Main(string[] args)
{
Uri oDataUri = new Uri(ODataEntityPath, UriKind.Absolute);
var context = new Resources(oDataUri);
context.SendingRequest2 += new EventHandler<SendingRequest2EventArgs>(delegate (object sender, SendingRequest2EventArgs e)
{
var authenticationHeader = OAuthHelper.GetAuthenticationHeader();
e.RequestMessage.SetHeader(OAuthHelper.OAuthHeader, authenticationHeader);
});
foreach (var legalEntity in context.Teams.AsEnumerable())
{
Console.WriteLine("Name: {0}", legalEntity.Name);
}
Console.ReadLine();
Exception
at Microsoft.OData.Client.QueryResult.ExecuteQuery()
at Microsoft.OData.Client.DataServiceRequest.Execute[TElement](DataServiceContext context, QueryComponents queryComponents)
Unauthorized
at Microsoft.OData.Client.DataServiceRequest.Execute[TElement](DataServiceContext context, QueryComponents queryComponents)
at Microsoft.OData.Client.DataServiceQuery`1.Execute()
at Microsoft.OData.Client.DataServiceQuery`1.GetEnumerator()
at ODataConsoleApplication.Program.Main(String[] args)
Auth logs
Activated Event Time Duration Thread
06/04/2016 9:55:13: 42dbc15a-e068-4f46-9e99-3e41b1820eb9 - AcquireTokenHandlerBase: === Token Acquisition finished successfully.
An access token was retuned:
Access Token Hash: UsxaQ/QZQ+opGz/PC55O5cWYBV8kh1uhvf/CG269WSc=
Refresh Token Hash: 8aKSzBXtBrxr+uVaqhnT/IEg1+gXOkDqq/WHp8SmaBk=
Expiration Time: 06/04/2016 10:55:12 +00:00
User Hash: f1MLHm5K8HDY7tRpkz4amU2+CVFL53JJq3Ybc5q53g0= 4.59s
Activated Event Time Duration Thread
Exception thrown: 'Microsoft.OData.Client.DataServiceQueryException' in Microsoft.OData.Client.dll
("An error occurred while processing this request.") 5.13s [18036] <No Name>
You must add your application in Dynamics in order for it to work.
See ​System administration > Setup > Azure Active Directory applications

Categories