-1

Is there any support for WebForms C# Applications (non-MVC) ? or a work-around? If I want to integrate an existing mature C# webforms app with office 365 authentication and don’t want to have to rewrite the whole application.

Anthony
  • 31
  • 1
  • 9
  • Which .Net Framework version are you using? If you're using >4.5.1, there is everything built-in. See http://www.asp.net/web-api/overview/security/external-authentication-services – Gimly Jun 22 '16 at 07:22
  • I have selected webforms for the template of my project with .Net Framework = 4.5 – Anthony Jun 22 '16 at 07:44
  • In the link that you have added, the example is with single page aplication – Anthony Jun 22 '16 at 07:45
  • The authentication part is not specific to the single page app and should work as well with your app – Gimly Jun 22 '16 at 09:53
  • I added the client ID and the client secret, but I am receiving the following error – Anthony Jun 22 '16 at 10:00
  • We're unable to complete your request – Anthony Jun 22 '16 at 10:00
  • https://login.live.com/err.srf?lc=1033#error=invalid_request&error_description=The+provided+value+for+the+input+parameter+'redirect_uri'+is+not+valid.+The+expected+value+is+'https://login.live.com/oauth20_desktop.srf'+or+a+URL+which+matches+the+redirect+URI+registered+for+this+client+application.&state=4fKNv0ANSDc5523FL__Izg_OufPPXBx6vziNtsmXa2cH5QJndLXJjch4laxavVOaRnPyhBxitmh-AQJItZA3WIL2M29GoIgzpHQDJfxPVadWEhlpPAwvwoYU3x5cmxOwLIsQBiVG-JDkB4BtvIp2JUFx-Q1C5pFvoQQMtlEFqF7gibYhUbDdFy4Hw6uKh0GHXMqm4bIGw8MC3BYTessty_8HyUCi9AX5DPaB9fiSuOBe_I2D-a5ZMul17MCTZwERC4LE1Q57yWLBuHBUnMORTA – Anthony Jun 22 '16 at 10:01
  • Do you have an idea what could be the problem ? – Anthony Jun 22 '16 at 10:01

1 Answers1

1

To implement the OAuth authentication from Azure AD, we can write the code to redirect the user to the login page using the code below(From Login button click):

   {
        var authority = "https://login.microsoftonline.com";
        var tenant = "common";
        var authorizeSuffix = "oauth2";

        var EndPointUrl = String.Format("{0}/{1}/{2}/authorize?", authority, tenant, authorizeSuffix);

        var clientId = "";
        var redirectURL = "http://localhost:56384/auth.aspx";         
        var parameters = new Dictionary<string, string>
            {
                { "response_type", "code" },
                { "client_id", clientId },
                { "redirect_uri", redirectURL },
                { "prompt", "login"}
            };

        var list = new List<string>();

        foreach (var parameter in parameters)
        {
            if (!string.IsNullOrEmpty(parameter.Value))
                list.Add(string.Format("{0}={1}", parameter.Key, HttpUtility.UrlEncode(parameter.Value)));
        }
        var strParameters = string.Join("&", list);
        var requestURL=String.Concat(EndPointUrl,strParameters);

        Response.Redirect(requestURL);

    }

After the user sign-in the Azure AD, it will redirect to the redirectURL which we configed on the Azure. We can config it to the specific page to get the AUTH Code and request the token. Here is an example:

Auth.aspx:

   protected void Page_Load(object sender, EventArgs e)
    {
        var authority = "https://login.microsoftonline.com";
        var tenant = "common";
        var authorizeSuffix = "oauth2";
        var EndPointUrl = String.Format("{0}/{1}/{2}", authority, tenant, authorizeSuffix);

        var code = Request.QueryString["code"].ToString();

        var clientId = "";
        var resource = "https://graph.microsoft.com";
        var secrect = "";
        var redirectURL = "http://localhost:56384/auth.aspx";

        //Request access token
        var parameters = new Dictionary<string, string>
            {
                { "resource", resource},
                { "client_id", clientId },
                { "code",  code},
                { "grant_type", "authorization_code" },
                { "redirect_uri", redirectURL},
                { "client_secret",secrect}
            };


        var list = new List<string>();

        foreach (var parameter in parameters)
        {
            if (!string.IsNullOrEmpty(parameter.Value))
                list.Add(string.Format("{0}={1}", parameter.Key, HttpUtility.UrlEncode(parameter.Value)));
        }
        var strParameters = string.Join("&", list);


        var content = new StringContent(strParameters, Encoding.GetEncoding("utf-8"), "application/x-www-form-urlencoded");

        var client = new HttpClient();

        var url = string.Format("{0}/token", EndPointUrl);

        var response = client.PostAsync(url, content).Result;

        var text = response.Content.ReadAsStringAsync().Result;

        var result = JsonConvert.DeserializeObject(text) as JObject;

        var AccessToken = result.GetValue("access_token").Value<string>();
        var RefreshToken = result.GetValue("refresh_token").Value<string>();

        Session["accessToken"] = AccessToken;
        Session["refreshToken"] = AccessToken;


        //add code read the user info from access token for login in


    }

For the detail of Authorization Code Grant Flow you can refer to here

Update

Extract the user name form access token:

string accessToken = "";

byte[] data = Convert.FromBase64String(accessToken.Split('.')[1]);
string decodedString = Encoding.UTF8.GetString(data);

JToken token = JObject.Parse(decodedString);            
Console.WriteLine(token["name"].Value<string>());
Fei Xue
  • 14,369
  • 1
  • 19
  • 27
  • Thanks, I was able to login with office 365 user. – Anthony Jun 27 '16 at 13:18
  • Is there a way to return in the auth.aspx page the username ? – Anthony Jun 27 '16 at 13:19
  • I have 2 types of users, and each one will be redirected to a different page. – Anthony Jun 27 '16 at 13:19
  • Yes. We are able to get the username in auth.aspx since we are already get the **accessToken**. – Fei Xue Jun 28 '16 at 02:02
  • The **accesstoken** contains various claims like 'First Name,Last Name,Name,User Principal Name'. The access token is base 64 encoded, we need to decode it and get the claims from the decoder string. I have updated the code in the post above. – Fei Xue Jun 28 '16 at 02:19
  • "error": "invalid_grant", "error_description": "AADSTS65001: The user or administrator has not consented to use the application with ID 'b2c5b4a2-94e9-4adb-8871-7d2a83733cad'. Send an interactive authorization request for this user and resource.\r\nTrace ID: baa2775d-8509-4e51-8731-8c1434ee9cc5\r\nCorrelation ID: 17b3969b-ff7a-40cb-b87e-b44973f663fa\r\nTimestamp: 2016-06-28 05:39:39Z", "error_codes": [ 65001 ], "timestamp": "2016-06-28 05:39:39Z", "trace_id": "baa2775d-8509-4e51-8731-8c1434ee9cc5", "correlation_id": "17b3969b-ff7a-40cb-b87e-b44973f663fa" } – Anthony Jun 28 '16 at 05:55
  • the url is equal to "https://login.microsoftonline.com/common/oauth2/token" and if I try it on the browser I receive Sorry, but we’re having trouble signing you in. We received a bad request. – Anthony Jun 28 '16 at 05:59
  • Additional technical information: Correlation ID: b8886a0e-c313-4bc3-9853-7814f47bf880 Timestamp: 2016-06-28 05:57:07Z AADSTS90056: This endpoint only accepts POST requests. – Anthony Jun 28 '16 at 05:59
  • What's the scope configed for the app? Based on the error, it seems you were using the scope which need to the admin to consent. In this scenario, the user which doesn't have the admin privilege not able to login the app until the admin grant the consent for all organization via using "admin consent" flow(append the **"prompt=admin_consent"** to the authorize request). More detail about it, please refer to [here](https://azure.microsoft.com/en-us/documentation/articles/active-directory-integrating-applications/) about the consent framework. – Fei Xue Jun 28 '16 at 06:26
  • To get the access token using the **Authorization Code Grant Flow**, 2 steps required. First is that user login the page to get the auth code. And the second step is that exchange the access token with auth code via **POST**. Please refer to [here](https://msdn.microsoft.com/en-us/library/azure/dn645542.aspx) for the details for this flow. – Fei Xue Jun 28 '16 at 06:30
  • I fixed the privelages for the user and know I ma having this error on this line byte[] data = Convert.FromBase64String(accessToken.Split('.')[1]); An exception of type 'System.FormatException' occurred in mscorlib.dll but was not handled in user code Additional information: Invalid length for a Base-64 char array or string. – Anthony Jun 28 '16 at 07:29
  • The access token contains three part(Header, Payload, Signature). The code above get the claims from payload. You can decode the **AccessToken** via [here](https://jwt.io/) to verify whether the access token is valid. – Fei Xue Jun 28 '16 at 07:39