Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
486 views
in Technique[技术] by (71.8m points)

c# - How to authenticate with OAuth to access EWS APIs

My web service is currently doing basic username/password authentication in order to subscribe the exchange user for receiving the events (like new mail event etc) like below:

var service = new ExchangeService(exchangeVersion)
                                  {
                                      KeepAlive = true,
                                      Url = new Uri("some autodiscovery url"),
                                      Credentials = new NetworkCredential(username, password)
                                  };

var subscription = service.SubscribeToPushNotifications(
                                    new[] { inboxFolderFoldeID },
                                    new Uri("some post back url"),
                                    15,
                                    null,
                                    EventType.NewMail,
                                    EventType.Created,
                                    EventType.Deleted,
                                    EventType.Modified,
                                    EventType.Moved,
                                    EventType.Copied);

Now, I am supposed to replace the authentication mechanism to use OAuth protocol. I saw some examples but all of them seem to be talking about authenticating the client (https://msdn.microsoft.com/en-us/library/office/dn903761%28v=exchg.150%29.aspx?f=255&MSPPError=-2147217396) but nowhere I was able to find an example of how to authenticate an exchange user with OAuth protocol. Any code sample will help a lot. Thanks.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's not clear what you mean with 'web service' and how you currently get the username and password. If that is some kind of website where the user needs to login or pass credentials, then you'll have to start an OAuth2 grant from the browser as in redirecting the clients browser to the authorize endpoint to start implicit grant or code grant. The user will be presented a login screen on the OAuth2 server (and not in your application), once the user logs in a code or access token (depending on the grant) will be returned to your application which you can use in the ExchangeService constructor.

If that 'web' service is some service that runs on the users computer you can use one of the methods described below.

Get AccessToken using AuthenticationContext

The example seems to be based on an older version of the AuthenticationContext class.

The other version seems to be newer, also the AcquireToken is now renamed to AcquireTokenAsync / AcquireTokenSilentAsync.

No matter which version you're using, you will not be able to pass username and password like you're doing in your current code. However, you can let the AcquireToken[Async] method prompt for credentials to the user. Which, let's be honest, is more secure then letting your application deal with those user secrets directly. Before you know, you'll be storing plain text passwords in a database (hope you aren't already).

In both versions, those methods have a lot of overloads all with different parameters and slightly different functionality. For your use-case I think these are interesting:

Prompt behavior auto, in both vesions, means: the user will be asked for credentials when they're not already cached. Both AuthenticationContext constructors allow you to pass a token-cache which is something you can implement yourself f.e. to cache tokens in memory, file or database (see this article for an example file cache implementation).

Get AccessToken manually

If you really want to pass in the user credentials from code without prompting the user, there is always a way around. In this case you'll have to implement the Resource Owner Password Credentials grant as outlined in OAuth2 specificatioin / RFC6749.

Coincidence or not, I have an open-source library called oauth2-client-handler that implements this for use with HttpClient, but anyway, if you want to go this route you can dig into that code, especially starting from this method.

Use Access Token

Once you have an access token, you can proceed with the samples on this MSDN page, f.e.:

var service = new ExchangeService(exchangeVersion)
                  {
                      KeepAlive = true,
                      Url = new Uri("some autodiscovery url"),
                      Credentials = new OAuthCredentials(authenticationResult.AccessToken))
                  };

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...