Reputation: 13
We are developing an application that consists out of multiple components. We have 2 Front-Ends (both using ASP.NET MVC) and 1 Back-End using ASP.NET MVC API.
We need to allow the user to authenticate themself with their O365 account (so on the Azure AD) and enable Single Sign On for these accounts. We have found several blogs and tried a lot but we keep receiving errors.
This is what we got so far
public class AccountController : BaseController
{
private string Authority = ConfigurationManager.AppSettings["ida:Authority"];
private string Audience = ConfigurationManager.AppSettings["ida:Audience"];
private string AzureClientId = ConfigurationManager.AppSettings["ida:AzureClientId"];
private string AppKey = ConfigurationManager.AppSettings["ida:AppKey"];
private string Tenant = ConfigurationManager.AppSettings["ida:Tenant"];
private static Uri RedirectUri { get; } = new Uri(ConfigurationManager.AppSettings["ida:RedirectUri"]);
private string BaseServiceUrl = ConfigurationManager.AppSettings["ida:BaseServiceUrl"];
public ActionResult LoginO365()
{
var authContext = new AuthenticationContext(Authority);
try
{
var result = Task.Run( async() => await authContext.AcquireTokenAsync(Audience, AzureClientId, RedirectUri, new PlatformParameters(PromptBehavior.Always))).Result;
/..
Some business code
../
return RedirectToAction("SomeAdminPage");
}
catch(Exception ex)
{
return View("Login");
}
}
}
We now receive an error on the line: var result = Task.Run( async() => await authContext.AcquireTokenAsync(Audience, AzureClientId, RedirectUri, new PlatformParameters(PromptBehavior.Always))).Result; We get the pop-up to log and can enter our password, but then the error is thrown.
The message is the following
{"AADSTS70002: The request body must contain the following parameter: 'client_secret or client_assertion'.\r\nTrace ID: 5042d7a7-4f18-433f-8e9d-424260fe1200\r\nCorrelation ID: 6a0cd62c-f5dd-4f7c-94b0-83df9edfb098\r\nTimestamp: 2017-03-24 11:53:06Z"} System.Exception {Microsoft.IdentityModel.Clients.ActiveDirectory.AdalServiceException}
This message has a different InnerException:
{" Response status code does not indicate success: 401 (Unauthorized)."} System.Exception {System.Net.Http.HttpRequestException}
An this message has yet another different InnerException:
{"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS70002: The request body must contain the following parameter: 'client_secret or client_assertion'.\\r\\nTrace ID: 5042d7a7-4f18-433f-8e9d-424260fe1200\\r\\nCorrelation ID: 6a0cd62c-f5dd-4f7c-94b0-83df9edfb098\\r\\nTimestamp: 2017-03-24 11:53:06Z\",\"error_codes\":[70002],\"timestamp\":\"2017-03-24 11:53:06Z\",\"trace_id\":\"5042d7a7-4f18-433f-8e9d-424260fe1200\",\"correlation_id\":\"6a0cd62c-f5dd-4f7c-94b0-83df9edfb098\"}"} System.Exception
Is someone having experience with this kind of code and who can direct us in the correct direction?
Thanks in advance!
Upvotes: 1
Views: 2385
Reputation: 27588
When using Authorization Code Flow in web app to acquire token for protected resource , you need to provide the client secret . You could use the OpenID Connect ASP.Net OWIN middleware, please refer to below links for code sample :
https://github.com/Azure-Samples/active-directory-dotnet-webapp-openidconnect https://github.com/Azure-Samples/active-directory-dotnet-webapp-multitenant-openidconnect (multi-tenant )
If you want to write your own code to achieve that , with ADAL , code below is for your reference :
get authorization code :
public ActionResult Contact()
{
string authorizationUrl = string.Format(
"https://login.microsoftonline.com/{0}/oauth2/authorize?response_type=code&client_id={1}&redirect_uri={2}",
tenantid, clientId, "http://localhost:44344/Home/CatchCode");
return Redirect(authorizationUrl);
}
acquire token via code :
public ActionResult CatchCode(string code)
{
string resource = "https://graph.windows.net";
AuthenticationContext authContext = new AuthenticationContext(Startup.Authority);
ClientCredential credential = new ClientCredential(clientId, appKey);
var accessToken =
authContext.AcquireTokenByAuthorizationCodeAsync(code,
new Uri("http://localhost:44344/Home/CatchCode"), credential, resource).Result.AccessToken;
return View();
}
Upvotes: 1