1

I have a Web API (all my code) method that I want to be called on a schedule from within Azure. I have it all working. I can specify the URL, set up a schedule and it works fine. What I want to do though is restrict the call to a certain 'system' user.

All other Web API methods are called from a Web Site. The Web site allows the user to login and receive an 'access token' and then that token is sent along with all other requests. So a two-step process. This all works fine too.

How do I pass the 'system' user/password to the Web API method from within the Azure scheduler? It looked pretty straight forward, choose Basic Authentication and then enter the user/password combination. It still calls the Web API method, but its not authenticated? I'm not sure how I get the User authenticated 'before' calling the Web API method?

Martin Brandl
  • 56,134
  • 13
  • 133
  • 172
Rob L
  • 2,124
  • 3
  • 22
  • 50

2 Answers2

1

You probably use an Identity Provider like Azure Active Directory. You should use a service principal which represents your schedule application that is allowed to call your API instead of user principal (your system user).

Read more: Application and service principal objects in Azure Active Directory (Azure AD)

So within the Authentication Settings you should choose Active Directory OAuth and provide the neccessary values:

enter image description here

Basic Authentication must be configured within your WebAPI, its not related to the token authentication which you are using.

Martin Brandl
  • 56,134
  • 13
  • 133
  • 172
0

It still calls the Web API method, but its not authenticated?

I'm not sure how I get the User authenticated 'before' calling the Web API method?

According to your description, it seems that you want to use Basic Authentication in Web API. Just like your guess, we could enter user name and password straight forward by using Basic Authentication. I have created a simple demo, if I want to read the data in Web API, I need to be authenticated first. You could refer to my code:

Code in Web API project

Create BasicAuthHttpModule.cs: (specific your user name and password)

public class BasicAuthHttpModule : IHttpModule
    {
        private const string Realm = "My Realm";

    public void Init(HttpApplication context)
    {
        // Register event handlers
        context.AuthenticateRequest += OnApplicationAuthenticateRequest;
        context.EndRequest += OnApplicationEndRequest;
    }

    private static void SetPrincipal(IPrincipal principal)
    {
        Thread.CurrentPrincipal = principal;
        if (HttpContext.Current != null)
        {
            HttpContext.Current.User = principal;
        }
    }

    // TODO: Here is where you would validate the username and password.
    private static bool CheckPassword(string username, string password)
    {
        return username == "peter" && password == "Password123!"; // you also could read user name and password from your Azure SQL database
    }

    private static void AuthenticateUser(string credentials)
    {
        try
        {
            var encoding = Encoding.GetEncoding("iso-8859-1");
            credentials = encoding.GetString(Convert.FromBase64String(credentials));

            int separator = credentials.IndexOf(':');
            string name = credentials.Substring(0, separator);
            string password = credentials.Substring(separator + 1);

            if (CheckPassword(name, password))
            {
                var identity = new GenericIdentity(name);
                SetPrincipal(new GenericPrincipal(identity, null));
            }
            else
            {
                // Invalid username or password.
                HttpContext.Current.Response.StatusCode = 401;
            }
        }
        catch (FormatException)
        {
            // Credentials were not formatted correctly.
            HttpContext.Current.Response.StatusCode = 401;
        }
    }

    private static void OnApplicationAuthenticateRequest(object sender, EventArgs e)
    {
        var request = HttpContext.Current.Request;
        var authHeader = request.Headers["Authorization"];
        if (authHeader != null)
        {
            var authHeaderVal = AuthenticationHeaderValue.Parse(authHeader);

            // RFC 2617 sec 1.2, "scheme" name is case-insensitive
            if (authHeaderVal.Scheme.Equals("basic",
                    StringComparison.OrdinalIgnoreCase) &&
                authHeaderVal.Parameter != null)
            {
                AuthenticateUser(authHeaderVal.Parameter);
            }
        }
    }

    // If the request was unauthorized, add the WWW-Authenticate header 
    // to the response.
    private static void OnApplicationEndRequest(object sender, EventArgs e)
    {
        var response = HttpContext.Current.Response;
        if (response.StatusCode == 401)
        {
            response.Headers.Add("WWW-Authenticate",
                string.Format("Basic realm=\"{0}\"", Realm));
        }
    }

    public void Dispose()
    {
    }
}

Code in web.config:

<modules>
<add name="BasicAuthHttpModule"
         type=" [your project name].[folder name].BasicAuthHttpModule, [your project name]"/>
<!--Just like this: WebApiAzure1.BasicAuthor.BasicAuthHttpModule,WebApiAzure1-->
</modules>

Code in Api Controller:

       [Authorize] //add authorize attribute for specific method
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

You could see the result like this:

enter image description here

Community
  • 1
  • 1
Janley Zhang
  • 1,567
  • 7
  • 11
  • Currently trying this code. Slow reply - moved house. The code runs and appears to work as expected. It's still saying unauthoised when it hits the controller action though. I'll investigate a bit more. – Rob L Feb 17 '18 at 02:07
  • Check your username and password. Please mak sure they are correct. – Janley Zhang Feb 17 '18 at 02:46
  • The code above is definitely being called with the correct User Id / Password. Looking into the documentation, it would seem that I need to use Azure Directory Services? – Rob L Feb 19 '18 at 01:04
  • 1
    No. I just provide a document about Basic Authentication in Web API. I suggest you could follow steps in above article(https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/basic-authentication). – Janley Zhang Feb 19 '18 at 01:30
  • if the reply help you solve the problem, you can mark it as answer to close this thread. – Janley Zhang Mar 07 '18 at 14:36
  • I still can't get this wot work in my case. It's still outstanding. Probably specific to my scenario. When I determine the answer I will post here. – Rob L Mar 29 '18 at 00:05