I'm currently building a cross domain messaging service that uses claims to communicate with services inside the domain. In my messaging service I have:
this.messageFactory = MessagingFactory.Create();
this.namespaceManager = NamespaceManager.Create();
TokenProvider tokenProvider = TokenProvider.CreateSamlTokenProvider(saml,
new Uri("https://<Messaging service>:9355/<Application Namespace>/"));
this.messageFactory.GetSettings().TokenProvider = tokenProvider;
this.namespaceManager.Settings.TokenProvider = tokenProvider;
where the saml variable is a string of xml representing my saml token.
Later on I call
if (this.namespaceManager.TopicExists(topicName) == false)
{
this.namespaceManager.CreateTopic(topicName);
}
When the if statement is called I get this error:
The token provider service was not avaliable when obtaining a token for 'https://<Messaging service>:9355/<Application Namespace>/WRAPv0.9/'.
With an inner exception of:
The remote server returned an error: (404) Not Found.
But when I browse to address I get a response in the web page:
<feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Publicly Listed Services</title><subtitle type="text">This is the list of publicly-listed services currently available.</subtitle><id>uuid:7ad43729-3ed5-4c35-9987-48a34036d267;id=4</id><updated>2013-09-24T17:50:26Z</updated><generator>Service Bus 1.0</generator></feed>
Any ideas if this is a config issue or am I missing something that's needed for my token?
Related
I am getting the following error when connecting to a NetSuite production account, through the Suitetalk API:
I don't have problems connecting to the Sandbox account for this client. I am connecting through a C# WCF project. I don't believe the problem is with the c# project, since this code is being used in Production with many other clients.
It seems to me like the SOAP message being returned is incorrectly formatted - there seems to be a line break before the 'soapenv' element in the SOAP message. I am getting this error when creating a "get" request against the API(using passport login). This error occurs on any API call though, I did try simply logging in through the API as well.
I have double checked the login details and account information for this client and everything seems in orders. Besides, if this information is incorrect, I should be getting authentication errors - not malformed SOAP messages.
Any help will be appreciated, thanks!
It turns out that I needed to use the webservices.na3.netsuite WSDL. I was under the impression that the regular "webservices.netsuite" WSDL would direct any requests to the correct server.
So when connecting to a NetSuite account through SuiteTalk, be sure to make use of the correct WSDL and specify the correct endpoint along with your login credentials. You can check which server your account is hosted on by looking at the URL when logged into your NetSuite account.
Update
I made use of the newest 'DataCenterAwareNetSuiteService' class to dynamically get the correct data center for the current account that I am trying to connect to:
class DataCenterAwareNetSuiteService : NetSuiteService
{
private System.Uri OriginalUri;
public DataCenterAwareNetSuiteService(string account, bool doNotSetUrl)
: base()
{
OriginalUri = new System.Uri(this.Url);
if (account == null || account.Length == 0)
account = "empty";
if (!doNotSetUrl)
{
//var temp = getDataCenterUrls(account);
DataCenterUrls urls = getDataCenterUrls(account).dataCenterUrls;
Uri dataCenterUri = new Uri(urls.webservicesDomain + OriginalUri.PathAndQuery);
this.Url = dataCenterUri.ToString();
}
}
public void SetAccount(string account)
{
if (account == null || account.Length == 0)
account = "empty";
this.Url = OriginalUri.AbsoluteUri;
DataCenterUrls urls = getDataCenterUrls(account).dataCenterUrls;
Uri dataCenterUri = new Uri(urls.webservicesDomain + OriginalUri.PathAndQuery);
this.Url = dataCenterUri.ToString();
}
}
The above is called like so:
new DataCenterAwareNetSuiteService("*account number*", false);
With the latest version of NetSuite, some changes have been made to URLs. For instance, now you can have more than one SandBox URL. Because of this, the URL format has changed. The account number used when authenticating is also now different. For sandboxes the account Id is now passed up as ACCOUNTNUMBER_SANDBOXID, for example 12345678_SB1.
You can determine the URLs for the SOAP and REST services by using the datacenterurls endpoint and supplying the account # you would like to determine the URLS for.
https://rest.netsuite.com/rest/datacenterurls?account=YOUR_ACCOUNT_NUMBER
The functionality below is based on the answer from #Charl above.
I have made a couple changes below that provides the same functionality without using inheritance.
This may be a simpler implementation for a newer programmer who does not know how to use an inherited class.
var accountId = "1234567"; // Insert your account ID here
var Service = new NetSuiteService();
Service.Url = new Uri(Service.getDataCenterUrls(accountId).dataCenterUrls.webservicesDomain + new Uri(Service.Url).PathAndQuery).ToString();
I downloaded the example below to get an access token from MS Graph and it worked fine. Now I changed the code to get a token from a custom web API. On apps.dev.microsoft.com I registered a client application and an the API.
Client and server registration in AD
private static async Task<AuthenticationResult> GetToken()
{
const string clientId = "185adc28-7e72-4f07-a052-651755513825";
var clientApp = new PublicClientApplication(clientId);
AuthenticationResult result = null;
string[] scopes = new string[] { "api://f69953b0-2d7f-4523-a8df-01f216b55200/Test" };
try
{
result = await clientApp.AcquireTokenAsync(scopes, "", UIBehavior.SelectAccount, string.Empty);
}
catch (Exception x)
{
if (x.Message == "User canceled authentication")
{
}
return null;
}
return result;
}
When I run the code I login to AD via the dialog en get the following exception in the debugger:
Error: Invalid client Message = "AADSTS65005: The application
'CoreWebAPIAzureADClient' asked for scope 'offline_access' that
doesn't exist on the resource. Contact the app vendor.\r\nTrace ID:
56a4b5ad-8ca1-4c41-b961-c74d84911300\r\nCorrelation ID:
a4350378-b802-4364-8464-c6fdf105cbf1\r...
Error message
Help appreciated trying for days...
For anyone still striking this problem, please read this:
https://www.andrew-best.com/posts/please-sir-can-i-have-some-auth/
You'll feel better after this guy reflects all of your frustrations, except that he works it out...
If using adal.js, for your scope you need to use
const tokenRequest = {
scopes: ["https://management.azure.com/user_impersonation"]
};
I spent a week using
const tokenRequest = {
scopes: ["user_impersonation"]
};
.. since that is the format that the graph API scopes took
As of today, the V2 Endpoint does not support API access other than the Microsoft Graph. See the limitations of the V2 app model here.
Standalone Web APIs
You can use the v2.0 endpoint to build a Web API that is secured with
OAuth 2.0. However, that Web API can receive tokens only from an
application that has the same Application ID. You cannot access a Web
API from a client that has a different Application ID. The client
won't be able to request or obtain permissions to your Web API.
For the specific scenario that you are trying to accomplish, you need to use the V1 App Model (register apps on https://portal.azure.com).
In the very near future, V2 apps will be enabled to call other APIs other than Microsoft Graph, so your scenario will be supported, but that is just not the case today. You should keep an eye out on our documentation for this update.
In your (server) application registration in AAD, you need to specify your scopes in the oauth2Permissions element.
You may already have a user_impersonation scope set. Copy that as a baseline, give it a unique GUID and value, and then AAD will let your client request an access token with your new scope.
I am trying to use the .NET SDK (2.3.35.0) and create an endpoint (APNS subscription). I already have an application defined in AWS and have an Application arn. I have one APNS token (endpoint) already stored and through the console I have been able to send push notifications to that device.
What I am having a hard time with is sending a createPlatformEndpoint to Amazon's SNS system. I am getting this error:
"Message": "An error has occurred.",
"ExceptionMessage": "Request is missing Authentication Token",
"ExceptionType": "Amazon.SimpleNotificationService.AmazonSimpleNotificationServiceException"
This is my method for sending the request:
public void addAPNSSubscription(string platformAppARN, string deviceToken)
{
using (var client = new AmazonSimpleNotificationServiceClient(_snsAccessKey, _snsSecretAccessKey, _snsClientConfig))
{
var endpointRequest = new CreatePlatformEndpointRequest { PlatformApplicationArn = platformAppARN, Token = deviceToken };
endpointRequest.CustomUserData = "Testing from .NET";
var result = client.CreatePlatformEndpoint(endpointRequest);
}
}
I am sure the missing Authentication Token is an OAuth token, I just don't know how to get that through the .NET SDK. Thanks in advance for the help.
I am stupid. I was using an existing class, and assumed the config properties were being read properly. They weren't. When I fixed that issue, the request went off without a problem.
I've tried 3 ways with no result:
According to this article https://msdn.microsoft.com/en-us/library/azure/ee460782.aspx I've registered new web application in AAD with permissions to Access Azure Service Management API (steps 1-9) and written the recommended two lines of code to acquire the token:
var context = new AuthenticationContext($"https://login.windows.net/{tenantId}");
var result = context.AcquireToken("https://management.core.windows.net/", clientId, new Uri(redirectUri));
, but it fails with the exception:
Microsoft.IdentityModel.Clients.ActiveDirectory.AdalServiceException was unhandled
Message: An unhandled exception of type 'Microsoft.IdentityModel.Clients.ActiveDirectory.AdalServiceException' occurred in Microsoft.IdentityModel.Clients.ActiveDirectory.dll
Additional information: AADSTS90014: The request body must contain the following parameter: 'client_secret or client_assertion'.
Trace ID: aa2d6962-5aea-4f8e-bed4-9e83c7631887
Correlation ID: f7f1a61e-1720-4243-96fa-cff182150931
Also I've tried:
var context = new AuthenticationContext($"https://login.windows.net/{tenantId}");
var result = context.AcquireToken("https://management.core.windows.net/", new ClientCredential(clientId, clientSecret));
where clientSecret is secret app key of my application.
This version returns a token, but requests with this token returns 403 Forbidden:The server failed to authenticate the request. Verify that the certificate is valid and is associated with this subscription.
The last, I've found http://blogs.msdn.com/b/cloud_solution_architect/archive/2015/03/02/authenticating-azure-service-management-api-with-azure-ad-user-credentials.aspx, which recommends:
var context = new AuthenticationContext(string.Format("https://login.windows.net/{0}", tenantId));
// TODO: Replace with your Azure AD user credentials (i.e. admin#contoso.onmicrosoft.com)
string user = "{YOUR-USERID]";
string pwd = "{YOUR-USER-PASSWORD}";
var userCred = new UserCredential(user, pwd);
AuthenticationResult result =
await context.AcquireTokenAsync("https://management.core.windows.net/", clientId, userCred);
but it also fails with the same exception as in the first case...
Could you please assist me?
You should change the "Application Type" to "NATIVE CLIENT APPLICATION" while creating the application in the Azure portal.
When I was trying to post messages to Twitter, the above error coming. How to get rid of that error?
The stacktrace is the following:
Exception = {"The remote server returned an error: (407) Proxy Authentication Required."} ExceptionStatus = ProtocolError
Code:
private string GetOAuthUrl()
{
IFluentTwitter twitter;
//Override the callback url if one was entered
if (CallbackUrl != null && CallbackUrl.Trim().Length > 0)
{
twitter = FluentTwitter.CreateRequest().Configuration.UseHttps().Authentication.GetRequestToken(ConsumerKey, ConsumerSecret, CallbackUrl);
}
else
{
twitter = FluentTwitter.CreateRequest().Configuration.UseHttps().Authentication.GetRequestToken(ConsumerKey, ConsumerSecret);
}
var response = twitter.Request();
UnauthorizedToken UnauthorizedToken = response.AsToken();
string AuthorizationUrl = FluentTwitter.CreateRequest().Authentication.GetAuthorizationUrl(UnauthorizedToken.Token);
return AuthorizationUrl;
}
If fluent twitter is using WebRequests under the covers, then you need to specify credentials for the proxy using code like this:
System.Net.WebRequest.DefaultWebProxy.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
This will tell all web requests to use the credentials of the user running the application to authenticate with the proxy.
To make this work, you will need to configure the application to run under a service account which has been granted access to the proxy server. You can then tie down this service account so that it has as few permissions as possible to run the service.
If your application needs to run under an account which doesn't have rights to use the proxy server, you can specify the credentials explicitly as follows:
System.Net.NetworkCredential credentials = new System.Net.NetworkCredential("username", "password", "domain");
System.Net.WebRequest.DefaultProxy.Credentials = credentials;
The down side to this is that you have to store those credentials somewhere, and that they could be captured by an attacker if they managed to compromise your application. In some environments, this is not acceptable from a security standpoint.