I'm trying to access the outlook 365 task api using a pre-defined microsoft account username and password which I will put in the config file.
Currently my app is redirecting to the microsoft login page using
HttpContext.GetOwinContext().Authentication.Challenge(
new AuthenticationProperties { RedirectUri = "/" },
OpenIdConnectAuthenticationDefaults.AuthenticationType);
And then I get the token under the current signed in user context.
string accessToken = await AuthProvider.Instance.GetUserAccessTokenAsync();
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer" + accessToken);
snippet of the GetUserAccessTokenAsync()
string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
HttpContextBase httpContextBase = HttpContext.Current.GetOwinContext().Environment["System.Web.HttpContextBase"] as HttpContextBase;
SessionTokenCache tokenCache = new SessionTokenCache(signedInUserID, httpContextBase);
Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext authContext = new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(SettingsHelper.Authority, tokenCache);
ClientCredential clientCredential = new ClientCredential(SettingsHelper.ClientId, SettingsHelper.ClientSecret);
string userObjectId = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
UserIdentifier userId = new UserIdentifier(userObjectId, UserIdentifierType.UniqueId);
try
{
AuthenticationResult result = await authContext.AcquireTokenSilentAsync(SettingsHelper.OutlookResourceId, clientCredential, userId);
return result.AccessToken;
}
catch (AdalException ex)
{
HttpContext.Current.Request.GetOwinContext().Authentication.Challenge(
new AuthenticationProperties() { RedirectUri = "/" },
OpenIdConnectAuthenticationDefaults.AuthenticationType);
throw new Exception(ex.Message);
}
But my goal is to remove this login and just use the fixed admin account to access the api.
is it possible to do get the token from a user credential which is different from the signed in one?
I'm trying to search for examples but I can't find anything that fits.
I'm quite new in using the API so i'm still learning. :)
Any ideas are very much appreciated.
Thank you in advance.
The first option (and perhaps the more secure option) would be to have a small onboarding flow through which you login with the admin, acquire a refresh token for them, and store that somewhere secure. Then you can use the refresh token whenever you need an access token. Though you have to remember to refresh the refresh token as well as it expires too. But you get a new refresh token every time you acquire a token with one, so should not be a problem. The greatest advantage this approach has is that it allows the admin account to have MFA etc., unlike the second option.
The second option is to use the Resource Owner Password Credentials Grant flow. I believe ADAL.NET does not give you access to an overload of AcquireTokenAsync that allows doing that from a confidential client, so you will have to make the HTTP call manually to get the tokens.
Here is an example of ROPC:
string tokenUrl = $"https://login.microsoftonline.com/mytenant.onmicrosoft.com/oauth2/token";
var req = new HttpRequestMessage(HttpMethod.Post, tokenUrl);
req.Content = new FormUrlEncodedContent(new Dictionary<string, string>
{
["grant_type"] = "password",
["client_id"] = "23d3be1b-a671-4452-a928-78fb842cb969",
["client_secret"] = "REDACTED",
["resource"] = "https://graph.windows.net",
["username"] = "[email protected]",
["password"] = "REDACTED"
});
using (var client = new HttpClient())
{
var res = await client.SendAsync(req);
string json = await res.Content.ReadAsStringAsync();
}
And the HTTP request:
POST https://login.microsoftonline.com/mytenant.onmicrosoft.com/oauth2/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: login.microsoftonline.com
Content-Length: 277
Expect: 100-continue
Connection: Keep-Alive
grant_type=password&client_id=23d3be1b-a671-4452-a928-78fb842cb969&client_secret=REDACTED&resource=https%3A%2F%2Fgraph.windows.net&username=testuser%40mytenant.onmicrosoft.com&password=REDACTED
The greatest downside of ROPC is that the user account cannot use MFA, nor can it be a federated user. I would prefer the first option personally, but it has its downsides too. Refresh tokens can become invalid for certain reasons, one of them being a password reset (though that would affect ROPC too).