Stream: implementers
Topic: How to authenticate with C# FHIR API to post to simplifier
Chris Munro (Sep 01 2017 at 10:25):
I'm trying to post a structure definition to a simplifier project, I have the project endpoint and tried the following but get an error 'unauthorised' using the code below
var uri = new Uri(simplifierEndpoint);
var uriWithCred = new UriBuilder(uri) { UserName = "myusername", Password = "mypassword" }.Uri;
var client = new FhirClient(uriWithCred);
FhirXmlParser parser = new FhirXmlParser();
StructureDefinition stdef = parser.Parse<StructureDefinition>(XMLstr); //XMLstr is file with profile
client.Create<StructureDefinition>(stdef);
I'm wondering if @Mirjam Baltus , @Ewout Kramer or @Michel Rutten could help?
Michel Rutten (Sep 01 2017 at 10:52):
Hi @Chris Munro, you should add the credentials to the http headers. In Forge we use a small utility class:
var _basicAuthDecorator = new BasicAuth(endpoint, credentials); // ... using (var client = new SimplifierWebClient(Timeout)) { // add basic authentication _basicAuthDecorator.AddAuthentication(client.Headers); client.Encoding = Encoding.UTF8; client.DownloadString(...) } --- BasicAuth.cs --- using System; using System.Net; using System.Text; namespace Forge.ViewModels { public sealed class BasicAuth { private readonly string authenticationType; private readonly ICredentials credentials; public Uri ServerUrl { get; private set; } // Initialize the endpoint URL and the credentials for authentication public BasicAuth(Uri serverUrl, ICredentials credentials) { this.credentials = credentials; ServerUrl = serverUrl; authenticationType = "Basic "; } // Initialize the endpoint URL and the credentials for authentication public BasicAuth(string serverUrl, ICredentials credentials) : this(new Uri(serverUrl), credentials) { } // Add basic authentication to the request public void AddAuthentication(WebHeaderCollection headers) { if (credentials == null) return; // no credentials given, proceed without authentication var networkCredentials = credentials.GetCredential(ServerUrl, authenticationType); if (networkCredentials.UserName == null) return; // no credentials given, proceed without authentication var encodedCredentials = Convert.ToBase64String(Encoding.UTF8.GetBytes(networkCredentials.UserName + ":" + networkCredentials.Password)); headers[HttpRequestHeader.Authorization] = authenticationType + encodedCredentials; } } }
Chris Munro (Sep 01 2017 at 14:11):
Thanks @Michel Rutten, is the URL https://stu3.simplifier.net/ELabTest2 the correct one to put in? I tried even with postman to post an XML file to this URL with the username/password in the header and I get a 404 not found error
Michel Rutten (Sep 01 2017 at 14:23):
Hi @Chris Munro, the project url appears to be correct.
I forgot to mention that you need to hook/override FhirClient.(On)BeforeRequest and add credential headers, e.g. using
basicAuthDecorator.AddAuthentication(rawRequest.Headers);
I can succesfully publish profiles to my Forge STU3 demo project on Simplifier, so there are no issues on the server.
Michel Rutten (Sep 01 2017 at 14:35):
I just realized that the logic I posted earlier is for retrieving a list of personal projects from Simplifier. This is a custom operation, not a FHIR call.
To actually publish a profile to Simplifier, Forge uses a specialized FhirClient with OnBeforeRequest hook to add http heades for credentials (using BasicAuth utility class above):
public sealed class SimplifierFhirClient : FhirClient { private readonly BasicAuth basicAuthDecorator; public SimplifierFhirClient(Uri serverUrl, ICredentials credentials, bool verifyFhirVersion = false) : base(serverUrl, verifyFhirVersion) { basicAuthDecorator = new BasicAuth(serverUrl, credentials); } public SimplifierFhirClient(Uri serverUrl, string projectName, ICredentials credentials, bool verifyFhirVersion = false) : this(new Uri(serverUrl, projectName), credentials, verifyFhirVersion) { } protected override void BeforeRequest(HttpWebRequest rawRequest, byte[] body) { base.BeforeRequest(rawRequest, body); // ER 22-03-2016 add default accept [Spark: bugfix 9c64d8a3 (8/1/2016)] PreferredFormat = ResourceFormat.Json; basicAuthDecorator.AddAuthentication(rawRequest.Headers); } // DEBUGGING #if DEBUG protected override void AfterResponse(HttpWebResponse webResponse, byte[] body) { base.AfterResponse(webResponse, body); // var s = System.Text.Encoding.UTF8.GetString(body); // System.IO.File.WriteAllText(@"D:\test.xml", s) } #endif }
Here's the calling logic:
var client = new SimplifierFhirClient(url, new NetworkCredential(userName, password)); T result; if (string.IsNullOrEmpty(resource.Id)) { result = client.Create(resource); } else { result = client.Update(resource); }
Chris Munro (Sep 01 2017 at 15:04):
Fab! Thank you @Michel Rutten that's really helpful. I was getting into a bit of a mess but with the last post I've managed to get it working.
Michel Rutten (Sep 01 2017 at 15:07):
Great, happy to help out!
Sorry for the confusing first post. Friday afternoon... ;p
Last updated: Apr 12 2022 at 19:14 UTC