2

I have an API method like this

[HttpGet]
public string UpdateComputerDescriptions()
{
    var cred = System.Net.CredentialCache.DefaultCredentials;
    UpdateDescriptionsAndTimestamp(System.Net.CredentialCache.DefaultNetworkCredentials);
    return "done";
}

And I've tried to call it from PowerShell with

$webclient = new-object System.Net.WebClient
$webclient.Credentials = new-object System.Net.NetworkCredential($username, $password, $domain)
$webpage = $webclient.DownloadString($url)

And

Invoke-WebRequest $url -Credential $creds

My problem is that I need to pass the $creds credentials to my UpdateDescrptionsAndTimestamp method.

However, when I check DefaultCredentials and DefaultNetworkCredentials objects in the API method, they don't contain any values (I'm expecting to see at least the username in there).

I even tried changing the signature to public string UpdateComputerDescriptions(NetworkCredential credential)

and calling with

Invoke-WebRequest $url -Body @{credential=$creds} -Credential $creds

But I get the same result.

How can I achieve this?

Note I do not want to pass in plain text (or - for that matter - encrypted) credentials, as the powershell script will eventually be run as the user and I'll just pass in the default credentials. I just need to know how I can retrieve this from inside the API

Bassie
  • 9,529
  • 8
  • 68
  • 159

1 Answers1

0

This is what I've gotten to work in the past (passing the creds through the Authorization header as Base64 encoded string:

C#

HttpContext httpContext = HttpContext.Current;
string authHeader = httpContext.Request.Headers["Authorization"];
if (authHeader == null || !authHeader.StartsWith("Basic"))
    throw new Exception("The authorization header is empty or isn't Basic.");
string encodedCredentials = authHeader.Substring("Basic".Length).Trim();
string credentialPair = Encoding.Unicode.GetString(Convert.FromBase64String(encodedCredentials));
var credentials = credentialPair.Split(new[] { ":" }, StringSplitOptions.None);
var username = credentials[0];
var password = credentials[1];

Powershell

$username = "username"
$password = "password"
$url = "yourUrl"
$credentials = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($username + ":" + $password))
Invoke-WebRequest -Uri $url -Headers @{Authorization = "Basic $credentials"}

However, you'd likely be better off creating a system for token based authentication (see link here)



EDIT for further explanation

in depth look at an example C# controller:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Http;

namespace Application.Controllers
{
    public class GetDataController : ApiController
    {
        public IEnumerable<string> Get()
        {
            var user = AuthUser(HttpContext.Current);

            var dataset = new List<string>();
            // code to populate dataset

            return dataset;
        }

        //** I would put this somewhere else in your application so you can reuse it **\\
        private static User AuthUser(HttpContext httpContext)
        {
            var authHeader = httpContext.Request.Headers["Authorization"];
            if (authHeader == null || !authHeader.StartsWith("Basic"))
                throw new Exception("The authorization header is empty or isn't Basic.");
            var encodedCredentials = authHeader.Substring("Basic".Length).Trim();
            var credentialPair = System.Text.Encoding.Unicode.GetString(Convert.FromBase64String(encodedCredentials));
            var credentials = credentialPair.Split(new[] {":"}, StringSplitOptions.None);
            var username = credentials[0];
            var password = credentials[1];

            var user = new User();
            // code to validate login & populate user model

            return user;
        }
    }
}

You may need to install the WebApi package.
In the Nuget Package Manager Console: Install-Package Microsoft.AspNet.WebApi

JED
  • 1,538
  • 2
  • 19
  • 47
  • JED I just get `'HttpContext' does not contain a definition for 'Current' and no extension method 'Current' accepting a first argument of type 'HttpContext' could be found (are you missing a using directive or an assembly reference?) [DSSTools]` on that first C# line – Bassie May 16 '18 at 23:56
  • Okay so I need to change that to just use static `HttpContext.Request.Headers`, but now for some reason the header comes through as `negotiate` and not `authorize`, probably because I have the `[authorize]` attribute on the controller – Bassie May 17 '18 at 00:06
  • You need to include the system.web namespace. There is also system.web.mvc.httpcontext, but that's not what you want. [See post here](https://stackoverflow.com/questions/18309239/cant-access-to-httpcontext-current) – JED May 17 '18 at 04:49