I use Office.js's getCallbackTokenAsync to load the token to pass to the backend.
In the backend, I use EWS to retrieve the email data. Here is how I perform the authentication.
ExchangeService service = new ExchangeService();
service.Url = new Uri(ewsUrl); //retrieved from getCallbackTokenAsync
service.Credentials = new OAuthCredentials(ewsToken);// retrieved from getCallbackTokenAsync
It works well in exchange online enviroment. However when tested in on-premise exchange server, I got this authentication error:
Error Message: The remote server returned an error: (401) Unauthorized.
Stack Trace: at System.Net.HttpWebRequest.GetResponse() at Microsoft.Exchange.WebServices.Data.EwsHttpWebRequest.Microsoft.Exchange.WebServices.Data.IEwsHttpWebRequest.GetResponse() at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.GetEwsHttpWebResponse(IEwsHttpWebRequest request)
I then found this doc says the Oauth2 authentication is only for exchange online. I guess I need to use this NTLM (Exchange on-premises only).
The major reason I use EWS instead of Graph or Rest is it supports on-premise server more naturally. So should I change the authentication here? I certainly do not want to ask user for username and password.
Or is there anything I need to do(maybe custom configuration) to make the on-premise exchange server support token authentication?
Related
I have created a PAT token for my user account in TFS Server 2017 (on-premises, not VSTS). Using Postman I am attempting to call the following REST API with Basic Auth:
GET http://{server:port}/tfs/DefaultCollection/_apis/projects?api-version=1.0
In response I get the following error:
TF401444: Please sign-in at least once as {Well Known SID for my user account} in a web browser to enable access to the service. - Microsoft Team Foundation Server
I have tried opening the same URL in Chrome and attempting to login with the PAT but with no success (the login is not completed). Any suggestions as to what I am missing here?
TFS seems to be recognising the PAT token as I receive a different error if I revoke it.
The issue here was the use of 'DefaultCollection' in the URI. I didn't have permissions on the default project collection in our TFS instance and needed to replace 'DefaultCollection' with the name of the collection I actually did have access to.
It seems obvious now, but the documentation didn't make it clear that this was a variable part of the URI so I had assumed the API was always hosted as part of the DefaultCollection.
I need to create an organizational feed to host nuget packages shared among projects on our Azure DevOps environment.
After several unsuccesful attempts and research, I discovered that the only way to create an organizational feed is, by design from Microsoft mouth, the Azure DevOps API.
Source for the claim : This question on VS dev community
and The MS docs on project-scoped feeds
Basically, I just need to be able to perform a POST here :
https://feeds.dev.azure.com/{organization}/_apis/packaging/feeds?api-version=5.1-preview.1
with the body :
{
"name": "{myfeedname}",
"hideDeletedPackageVersions": true,
"upstreamEnabled": true
}
And of course, a Bearer token to authenticate myself. That's the point where I'm confused.
What is the simplest way to obtain one ? I'm logged in through my company Microsoft AD account on my computer browser on Azure DevOps. I don't see any Bearer token that I can "steal" to use in PostMan in my browser dev tools.
The API docs described some relevant info, but I'm confused on how to use it in Postman :
Security oauth2
Type: oauth2
Flow: accessCode
Authorization URL: https://app.vssps.visualstudio.com/oauth2/authorize&response_type=Assertion
Token URL: https://app.vssps.visualstudio.com/oauth2/token?client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
Scopes Name Description
vso.packaging_write Grants the ability to
create and read feeds and packages.
Here is the interface in Postman for OAuth2:
Ican see how the info in the docs relates to the fields 1 - 2 - 3 - 4, but then, what callback url should I use ? What credentials ? my Microsoft email + password from AD ?
I tried this, and all I seem to get is this from Postman :
{"$id":"1","innerException":null,"message":"A potentially dangerous Request.Path value was detected from the client (&).","typeName":"System.Web.HttpException, System.Web","typeKey":"HttpException","errorCode":0,"eventId":0}
TLDR
How do I properly proceed to get a token with Postman, or other tool to manually execute my one-time request to Azure DevOps REST API ?
notes :
Following info here : Unable to get Authorization code for Devops using Postman oAuth2.0
, leading here : https://github.com/Microsoft/azure-devops-auth-samples/tree/master/OAuthWebSample , I understand that I have to register and run a whole web application. Am I understanding this correctly ? I there a simpler way ?
I understand that I have to register and run a whole web application. Am I understanding this correctly ? I there a simpler way ?
Yes, you are right. You have to register whole web application.
As the interface in Postman for OAuth2, we need provide the CallbackUrl, ClientID, ClientSecret and so on. Then, we check the document Requesting an OAuth 2.0 token, we could to know the Callback URL is:
The client application callback URL redirected to after auth, and that
should be registered with the API provider.
So, we have to register an OAuth client app in Azure DevOps (https://app.vsaex.visualstudio.com/app/register), then we could get the following information, like:
You could check the document Authorize access to VSTS REST APIs with OAuth 2.0 for some more details.
AFAIK, there is currently no simpler way to get a bearer token to send requests to the Azure DevOps API.
Hope this helps.
I can use the Javamail IMAP package to access my outlook.office365.com mailbox. I want to access the same mailbox by using OAuth2.0. According to https://javaee.github.io/javamail/OAuth2, after 1.5.5 JavaMail is able to support OAuth2 by using the Bearer access token. I created a simple testing code:
System.out.println("Helloworld");
String host="outlook.office365.com";
String username="mymailboxname";
//String password="mymailboxpasswd";
String accesstoken="eyJ0eXAiOiJKV1QiLCJub25jZSI6Im4....my token from Micorsoft .....S0QoWgvodHXw";
Properties props=new Properties();
props.setProperty("mail.imap.ssl.enable","true");
props.setProperty("mail.imap.auth.mechanisms","XOAUTH2"); //added for oauth2
// set any other needed mail.imap.* properties here
Session session=Session.getInstance(props);
Store store=session.getStore("imap");
// store.connect(host,993,username,password);
store.connect(host,993,username,accesstoken);
When I ran it, I got AuthenticationFailedException
Exception in thread "main" javax.mail.AuthenticationFailedException: AUTHENTICATE failed.
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:732)
at javax.mail.Service.connect(Service.java:366)
at Main.main(Main.java:21)
What is the way to connect to outlook.office365.com with IMAP by using OAuth2
Found on here
Note
If you've enabled security defaults in your organization, POP3 and IMAP4 are automatically disabled in Exchange Online. For more information, see What are security defaults?.
To protect your Exchange Online tenant from brute force or password spray attacks, your organization will need to Disable Basic authentication in Exchange Online and only use Modern authentication in Exchange Online. Disabling Basic authentication will block legacy protocols, such as POP and IMAP.
I've set up something called the Data Export Service for Dynamics 365 so that it replicates into an Azure SQL database. This is working as expected.
I'm trying to find a way to be proactively notified if this service encounters any errors. There does not appear to be a native way to do this through the setup in CRM itself, but they do provide an API. The Swagger page outlining all methods can be found here.
I'm trying to call the GetProfilesByOrganizationId method using Postman:
https://discovery.crmreplication.azure.net/crm/exporter/profiles?organizationId=4ef7XXXX-XXXX-XXXX-XXXX-XXXXXX8a98f&status=true
I'm having issues with authentication and always receive the following error:
"Message": "Received unauthenticated requestRequest Url https://discovery.crmreplication.azure.net/crm/exporter/profiles?organizationId=4ef7XXXX-XXXX-XXXX-XXXX-XXXXXX8a98f&status=true"
I have registered an application in Azure that has permission to access Dynamics 365 on behalf of the authenticated user which in this case is me, the administrator.
I have set the Type to OAuth 2.0 on the Authorization tab of Postman. I have requested an Access Token using the Grant Type of Authorization Code against the above application successfully. This has added a header to the request:
Key: Authorization
Value: Bearer BIGLONGACCESSTOKEN
Despite this header being present I still get the error mentioned above.
The API documentation implies the authentication is OAuth2 Implicit Grant Flow (click on any red exclamation mark in the documentation) but I can't get this to work in Postman. When I try to request a token with this method I get the error:
unsupported_response_type
... in the Postman console.
Any ideas how to authenticate (with Implicit Grant?) against this API in Postman?
(I'd accept C# examples if they're more appropriate, but I'd be surprised if Postman can't show me what I need)
It looks like the code sample shown by Microsoft can work if updated with newer methods and with some extra configuration in Azure that's not documented.
Azure configuration
By installing the Data Export service (and assuming it's all working) you'll have a new Enterprise Application listed in Azure AD as Crm Exporter.
To take advantage of this application and authenticate with the Data Export API you must configure an app of your own.
Go to the App registrations tab in Azure AD and add a new application registration.
Give it a name and set the Application type to Native. The redirect URI doesn't typically matter as long as it's valid.
Click the Manifest button to edit the manifest, change the property oauth2AllowImplicitFlow to true and save the changes.
The only other important configuration is Required permissions which should be set as below:
Windows Azure Active Directory
Delegated permissions
Sign in and read user profile
Data Export Service for Microsoft Dynamics 365 (Crm Exporter)
Delegated permissions
Have access to Data Export Service for Microsoft Dynamics 365 API
You will then need to click Grant Permissions.
C# changes
The updated method looks like this:
using Microsoft.IdentityModel.Clients.ActiveDirectory;
string clientId = "11cfXXXX-XXXX-XXXX-XXXX-XXXXXXXXd020";
string user = "my.username#domain.com";
string password = "PASSWORD";
var authParam= await AuthenticationParameters.CreateFromResourceUrlAsync(
new Uri("https://discovery.crmreplication.azure.net/crm/exporter/aad/challenge")
);
var context = new AuthenticationContext(authParam.Authority, false);
var credentials = new UserPasswordCredential(user, password);
var token = await context.AcquireTokenAsync(authParam.Resource, clientId, credentials).AccessToken;
You can now query the Data Export API by providing the token as a header:
Authorization : Bearer eJ0y........Hgzk
curl -X GET --header 'Accept: application/json' 'https://discovery.crmreplication.azure.net/crm/exporter/profiles?organizationId=MyOrgId&status=true'
I am working on a proof of concept using Azure Active Directory Access Control Fig. 4 at The fundamentals of Azure identity management is the model I am shooting for. Since I need manage my own identifies in a deep heritage SaaS solution, I am setting up my own OpenID provider. For that, I am using DotNotOpenAuth. In my very vanilla, "hello world" example, I built a simple MVC app and registered it in my Access Control Service Namespace as a Relying Party Application and also registered the OpenIdProviderMvc project as-is from DotNetOpenAuth.Samples as my OpenID Provider using ACS Management Service. Here is the view I registered,
var openIdAddress = new IdentityProviderAddress
{
Address = "...localhost...",
EndpointType = "SignIn"
};
svc.AddRelatedObject(openId, "IdentityProviderAddresses", openIdAddress);
svc.SaveChanges();
which is the OpenID Provider endpoint page expecting to receive OpenID authentication messages to allow users to log into other web sites. This works well, when I launch my relying party application, where I installed the appropriate Nuget packages for DotNetOpenAuth (core, relying party, and their dependencies), the OpenID Providers gets called from the configuration in ACS and log in is successful. However, on redirection to ACS sending to my namespace the OpenID response, (...accesscontrol.windows.net/v2/openid?...) I get the error response:
An error occurred while processing your request.
HTTP Error Code: 502
Message: ACS30000: There was an error processing a sign-in response sent to the OpenID endpoint.
Inner Message: ACS30001: Unable to verify the OpenID response signature.
Inner Message: ACS90005: External server error.
Trace ID: 41338728-fd6e-4299-9efb-ad8684976aae
Timestamp: 2015-08-10 19:18:28Z
I am trying to figure our what I need to do to help ACS be able to verify the OpenID response signature. The response looks good (formatted for legibility and so I don't exceed my link restriction for low reputation):
https://....accesscontrol.windows.net/v2/openid?
context=cH...2
openid.claimed_id=.../user/bob
openid.identity=.../user/bob
openid.sig=NU...Rs=
openid.signed=claimed_id,identity,assoc_handle,op_endpoint,return_to,response_nonce,ns.alias3,alias3.mode,alias3.type.alias1,alias3.value.alias1,alias3.type.alias2,alias3.value.alias2,ns.sreg,sreg.email,sreg.fullname
openid.assoc_handle=WWcF!...
openid.alias3.type.alias2=.../namePerson&openid.alias3.value.alias2=bob
openid.ns.sreg=...openid.net/extensions/sreg/1.1
openid.sreg.email=bob#dotnetopenauth.net
openid.sreg.fullname=bob
Is this something I should be able to handle in the Rule Groups? Is there something I am missing in the security between my OpenId provider and ACS, such as sending some information back relating to signing algorithm, thumbprint, or something?
Thank you