Unable to Call API using my identity server from a native application

Someone asked on Stack Overflow:

I would like to make a Identity server and the API in two separate dockers for a native application (client mobile). It is running on an NGINX Reverse Proxy and Let’s Encrypt.

                               Dockers
                     ---------------------------
                    |       Reverse Proxy       |
                    |  -----------------------  |
   --------         | |    ----------------   | |
  | Mobile | ---------|-> | IdendityServer |  | |
   --------         | |   |   Port: 5000   |  | |
       |            | |    ----------------   | |
       |            | |            |          | |
       |            | |    ----------------   | |
       ---------------|-> |      API       |  | |
                    | |   |   Port: 5001   |  | |
                    | |    ----------------   | |
                    |  -----------------------  |
                    |                           |
                    |      ----------------     |
                    |     |   PostgreSQL   |    |
                    |     |   Port: 5432   |    |
                    |      ----------------     |
                     ---------------------------

With my current configuration:

  • The Reverse Proxy with Let’s Encrypt is well working from the mobile
  • The call API without [Authority] is well working from the mobile
  • The Identity server connection with the Hybrid flow is working and my user’s claims is listed

My codes are below.

IdentityServer Dockerfile

FROM microsoft/dotnet:2.0-sdk
COPY is4/* /app/
WORKDIR /app

ENV ASPNETCORE_URLS http://*:5000
EXPOSE 5000

ENTRYPOINT ["dotnet", "IdentityServer.dll"]

API Dockerfile

FROM microsoft/dotnet:2.0-sdk
COPY api/* /app/
WORKDIR /app

ENV ASPNETCORE_URLS http://*:5001
EXPOSE 5001

ENTRYPOINT ["dotnet", "ApiServer.dll"]

DockerCompose

version: '3'

services:
  identityserver:
    image: identityserver
    build:
      context: .
      dockerfile: IdentityServer/Dockerfile
    container_name: ids
    restart: always
    ports:
      - 5000:5000
#    expose:
#      - "5000"
    environment:
      ASPNETCORE_ENVIRONMENT: Development
      VIRTUAL_PORT: 5000
      VIRTUAL_HOST: ids.mydomain.com
      LETSENCRYPT_HOST: ids.mydomain.com
      LETSENCRYPT_EMAIL: myuser@mydomain.com
      IDENTITY_ISSUER: "https://ids.mydomain.com"
      IDENTITY_REDIRECT: "com.mobiletest.nativeapp"
      IDENTITY_CORS_ORIGINS: "https://ids.mydomain.com"
    depends_on:
      - db
  apiserver:
    image: apiserver
    build:
      context: .
      dockerfile: ApiServer/Dockerfile
    container_name: api
    restart: always
    ports:
      - 5001:5001
#    expose:
#      - "5001"
    environment:
      ASPNETCORE_ENVIRONMENT: Development
      VIRTUAL_PORT: 5001
      VIRTUAL_HOST: api.mydomain.com
      LETSENCRYPT_HOST: api.mydomain.com
      LETSENCRYPT_EMAIL: myuser@mydomain.com
      IDENTITY_AUTHORITY: "http://identityserver:5000"
      CLIENT_CORS_ORIGINS: "com.mobiletest.nativeapp"
    depends_on:
      - identityserver
      - db
    links:
      - identityserver
  db:
    image: postgresql:10
    build:
      context: .
      dockerfile: PostgreSQL/Dockerfile
    container_name: db
    restart: always
    ports:
      - "5432:5432"
    volumes:
      - /www/database:/var/lib/postgresql/data
    environment:
      - PGDATA=/var/lib/postgresql/data/pgdata

networks:
    default:
       external:
         name: nginx-proxy

IdentityServer Startup Code

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection")));
    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    // Add application services.
    services.AddTransient<IEmailSender, EmailSender>();

    services.AddMvc();

    // Configure identity server with in-memory stores, keys, clients and scopes
    services.AddIdentityServer(opt =>
    {
        opt.IssuerUri = Configuration["IDENTITY_ISSUER"];
        opt.PublicOrigin = Configuration["IDENTITY_ISSUER"];
    })
    .AddCorsPolicyService<InMemoryCorsPolicyService>() // Add the CORS service
    .AddDeveloperSigningCredential()
    .AddInMemoryPersistedGrants()
    .AddInMemoryIdentityResources(Config.GetIdentityResources())
    .AddInMemoryApiResources(Config.GetApiResources())
    .AddInMemoryClients(Config.GetClients())
    .AddAspNetIdentity<ApplicationUser>();

    services.AddAuthentication();

    // preserve OIDC state in cache (solves problems with AAD and URL lenghts)
    services.AddOidcStateDataFormatterCache("aad");

    // add CORS policy for non-IdentityServer endpoints
    services.AddCors(options =>
    {
        options.AddPolicy("CorsPolicy", policy =>
        {
            policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();
        });
    });
} // ConfigureServices()

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseBrowserLink();
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseStaticFiles();

    app.UseIdentityServer();

    app.UseForwardedHeaders(new ForwardedHeadersOptions
    {
        ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
    });

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
} // Configure()

IdentityServer Config Code

public static IEnumerable<IdentityResource> GetIdentityResources()
{
    return new List<IdentityResource>
    {
        new IdentityResources.OpenId(),
        new IdentityResources.Profile()
    };
}

public static IEnumerable<ApiResource> GetApiResources()
{
    return new List<ApiResource>
    {
        new ApiResource("api1", "My API")
        {
            ApiSecrets = { new Secret("secret".Sha256()) }
        }
    };
}

public static IEnumerable<Client> GetClients()
{
    // client credentials client
    return new List<Client>
    {
        new Client
        {
            ClientId = "native.hybrid",
            ClientName = "Native Client (Hybrid with PKCE)",
            AllowedGrantTypes = GrantTypes.Hybrid,
            RequirePkce = true,
            RequireConsent = false,
            //RequireClientSecret = false,
            ClientSecrets = { new Secret("secret".Sha256()) },                   
            RedirectUris = { Configuration["IDENTITY_REDIRECT"] + "://signin-oidc" },
            PostLogoutRedirectUris = { Configuration["IDENTITY_REDIRECT"] + "://signout-callback-oidc" },
            AllowedScopes = { "openid", "profile" },
            AllowedCorsOrigins = { Configuration["IDENTITY_CORS_ORIGINS"] },
            AllowOfflineAccess = true,
            //AllowAccessTokensViaBrowser = true
            RefreshTokenUsage = TokenUsage.ReUse
        }
    };
} // GetClients()

Api Config code

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvcCore()
        .AddAuthorization()
        .AddJsonFormatters();
    if (Configuration["CLIENT_CORS_ORIGINS"] == "")
    {
        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy",
                builder => builder
                .AllowAnyMethod()
                .AllowAnyOrigin()
                .AllowAnyHeader());
        });
    }
    else
    {
        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy",
                builder => builder
                .AllowAnyHeader()
                .AllowAnyMethod()
                .WithOrigins(Configuration["CLIENT_CORS_ORIGINS"]));
        });
    }
    services.AddAuthentication("Bearer");
    services.AddAuthentication(options => //adds the authentication services to DI
    {
        //We are using a cookie as the primary means to authenticate a user (via “Cookies” as the DefaultScheme). We set the DefaultChallengeScheme to “oidc” because when we need the user to login, we will be using the OpenID Connect scheme.
        options.DefaultScheme = "Cookies";
        options.DefaultChallengeScheme = "oidc";
    })
        .AddCookie("Cookies")       //add the handler that can process cookies
        .AddOpenIdConnect("oidc", options => //configure the handler that perform the OpenID Connect protocol
        {
            options.SignInScheme = "Cookies"; //is used to issue a cookie using the cookie handler once the OpenID Connect protocol is complete
            options.Authority = Configuration["IDENTITY_AUTHORITY"]; //indicates that we are trusting IdentityServer
            options.RequireHttpsMetadata = false;
            options.ClientId = "native.hybrid";
            options.SaveTokens = true;
            options.ClientSecret = "secret"; //used to persist the tokens from IdentityServer in the cookie
            options.ResponseType = "code id_token";
        });

    services.AddMvc();
} // ConfigureServices()

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseAuthentication();

    app.UseCors("CorsPolicy");

    app.UseForwardedHeaders(new ForwardedHeadersOptions
    {
        ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
    });

    app.UseMvc();
} // Configure()

API Controller code

[Route("api/[controller]")]
[EnableCors("CorsPolicy")]
[Authorize]
public class ValuesController : Controller
{
    // GET api/values
    [HttpGet]
    public IEnumerable<string> Get()
    {
        return new string[] { "testvalue1", "testvalue2" };
    }
} 

On Xamarin for the client mobile

var options = new OidcClientOptions
{
    Authority = "https://ids4.syladebox.com",
    ClientId = "native.hybrid",
    ClientSecret = "secret",
    //Scope = "openid profile api1 offline_access",
    Scope = "openid profile offline_access",
    ResponseMode = OidcClientOptions.AuthorizeResponseMode.Redirect,

    RedirectUri = "com.mobiletest.nativeapp://signin-oidc",
    PostLogoutRedirectUri = "com.mobiletest.nativeapp://signout-callback-oidc",

    //Flow = OidcClientOptions.AuthenticationFlow.Hybrid,
    //Policy = policy,

    //Browser = new SFAuthenticationSessionBrowser()
    // new in iOS 12
    Browser = new ASWebAuthenticationSessionBrowser()
    //Browser = new PlatformWebView()
};

_client = new OidcClient(options); 

var result = await _client.LoginAsync(new LoginRequest());

if (result.IsError)
{
    OutputText.Text = result.Error;
    return;
}

if (result.AccessToken != null)
{
    var client = new HttpClient();
    client.SetBearerToken(result.AccessToken);
    var response = await client.GetAsync("https://api.mydomain.com/api/values");
    if (!response.IsSuccessStatusCode) 
    {
        OutputText.Text = response.ReasonPhrase;
        return;
    }

    var content = await response.Content.ReadAsStringAsync();
    OutputText.Text = JArray.Parse(content).ToString();
}

Problem not resolved:

The problem is to unable to invoke the API on behalf of my user. It returns either or “No authorized” either or “Bad gateway” after:

response = await client.GetAsync("https://api.mydomain.com/api/values"); 

These errors are depending of the environment variables in the IdentityServer and Api dockers.

My current environment variables are:

IDENTITY_ISSUER: “https://ids.mydomain.com

IDENTITY_REDIRECT: “com.mobiletest.nativeapp”

IDENTITY_CORS_ORIGINS: “https://ids.mydomain.com

IDENTITY_AUTHORITY: “http://identityserver:5000

CLIENT_CORS_ORIGINS: “com.mobiletest.nativeapp”

The API call (https://api.mydomain.com/api/values) returns “Bad gateway”.

I think that IDENTITY_ISSUER, IDENTITY_REDIRECT are corrects because the Identity server connexion is successful.

Is the problem coming from the other environment variables (IDENTITY_CORS_ORIGINS, IDENTITY_AUTHORITY and CLIENT_CORS_ORIGINS) or the Identity Server/API codes?

Update January, 26:

To make sure if my API program works, I redid the API program to the simplest:

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();

            services.AddAuthentication("Bearer")
                .AddIdentityServerAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme, options =>
                 {
                     options.Authority = Configuration["IDENTITY_AUTHORITY"];
                     options.ApiName = "api";
                     //options.ApiSecret = "secret";
                 });

            // Add CORS policy for non-IdentityServer endpoints
            services.AddCors(options =>
            {
                options.AddPolicy("api", policy =>
                {
                    policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();
                });
            });
        } // ConfigureServices()

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseAuthentication();

            app.UseCors("api");

            app.UseForwardedHeaders(new ForwardedHeadersOptions
            {
                ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
            });

            app.UseMvc();
        } // Configure()

with the api controller:

    [Route("api/[controller]")]
    [Authorize(AuthenticationSchemes = IdentityServerAuthenticationDefaults.AuthenticationScheme)]
    public class ValuesController : Controller
    {
        // GET api/values
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "testvalue1", "testvalue2" };
        }
     }

and I use in my first test the other identity server :

demo.identityserver.io

For this test, I make the following configuration:

  apiserver:
    ...
    ports:
      - 5001:80
    environment:
      ...
      IDENTITY_AUTHORITY: "https://demo.identityserver.io"
      #CLIENT_CORS_ORIGINS (omitted in the code)

My OidcClientOptions in the client code is:

            var options = new OidcClientOptions
            {
                Authority = "https://demo.identityserver.io",
                ClientId = "native.hybrid",
                Scope = "openid profile email api offline_access",
                ResponseMode = OidcClientOptions.AuthorizeResponseMode.Redirect,

                RedirectUri = "com.mobiletest.nativeapp://callback",
                PostLogoutRedirectUri = "com.mobiletest.nativeapp://callback",
                Browser = new ASWebAuthenticationSessionBrowser()
            };

The login function is in my first topic.

  • The Identity server connection with the Hybrid flow is working
  • The API call is successful!

As demo.identityserver.io is the demonstration identity server, I have a doubt if it works as the case of production then I tested an other identity server (Okta) with the same API program:

dev-xxxxxx.okta.com

For this test, I make the following configuration:

  apiserver:
    ...
    ports:
      - 5001:80
    environment:
      ...
      IDENTITY_AUTHORITY: "https://dev-xxxxxx.okta.com"
      #CLIENT_CORS_ORIGINS (omitted in the code)

My OidcClientOptions in the client code is:

            var options = new OidcClientOptions
            {
                Authority = "https://dev-xxxx.okta.com",
                ClientId = "xxxxxxxxxxxxxxxxxxx", // ClientId is hidden in this topic

                Scope = "openid profile email offline_access",
                ResponseMode = OidcClientOptions.AuthorizeResponseMode.Redirect,

                RedirectUri = "com.okta.dev-xxxxxx:/callback",
                PostLogoutRedirectUri = "com.okta.dev-xxxxxx:/callback",

                Browser = new ASWebAuthenticationSessionBrowser()
            };
  • The Identity server connection with the Hybrid flow is working
  • The API call isn’t working, it returns the message “Unauthorized”.

With the two tests, I can not tell if my API program works well.

Could you help me? Thank you very much!

I posted the following answer, which was chosen as the accepted answer:

Have you tried using .AddJwtBearer() in your API instead of just .AddAuthentication("Bearer")?

Something like this:

services.AddAuthentication("Bearer")
    .AddJwtBearer("Bearer", options =>
    {
        options.Authority = "http://localhost:5000";
        options.RequireHttpsMetadata = false;
        options.Audience = "api1";
    });

Source: http://docs.identityserver.io/en/latest/quickstarts/1_client_credentials.html

While the source is referring to client credentials, I think you probably want to be using Jwt Tokens regardless of the client type.


Originally posted on Stack Overflow — 0 upvotes (accepted answer). Licensed under CC BY-SA.

Graphing United States Road/Highway Lane Mileage by State and Type Of Road

There are a few data visualization projects I want to tackle and a good number of them have a cartography component. I knew I had to get started with one and build on it or I’d never get any of them rolling. I ran across a ‘Functional System Lane Length’ data set from Federal Highway Administration. I figured the table could be cleaned up and presented in a more intuitive way using a map and it would force me to kick start this little prototype.

This is what I came up with, its still a work in progress, though updates will likely come slowly and will be applied to the next data visualization project. This is how I approached it.

Visualization Technology

I had worked with jqvmap on some previous projects, and they have a great sample for color coding a map based on a set of data, so I decided to stick with something I already knew. I also knew I wanted to throw this in a separate page that I could embed on my blog here, so I wanted to make sure it could be completely self contained. Data Processing

The data was available in an html table form, as well as pdf and excel. I found an online html table to json converter, and used that to build an array of data from the table. This got me close to what I wanted, but it left a bad taste in my mouth indexing into a multi dimensional array to pull out data every time I wanted to change data sets. This is what it looked like before any conversion:

[
    ["INTERSTATE","OTHER FREEWAYS AND EXPRESSWAYS","OTHER PRINCIPAL ARTERIAL","MINOR ARTERIAL","MAJOR COLLECTOR","MINOR COLLECTOR (2)","LOCAL (2)","TOTAL","INTERSTATE","OTHER FREEWAYS AND EXPRESSWAYS","OTHER PRINCIPAL ARTERIAL","MINOR ARTERIAL","MAJOR COLLECTOR","MINOR COLLECTOR","LOCAL (2)","TOTAL","",""  ],
    ["Alabama","2,414","-","6,045","8,398","24,615","12,441","94,725","148,638","2,189","138","4,905","6,070","7,547","372","41,481","62,701","211,339"  ],
    ["Alaska","2,057","-","1,612","867","2,743","2,862","15,294","25,434","303","-","503","475","510","472","3,898","6,162","31,597"  ],
    ["Arizona","3,714","70","3,417","2,691","8,552","3,789","61,350","83,584","1,462","1,552","3,771","9,278","4,352","456","40,505","61,375","144,959"  ],
    ["Arkansas","1,752","288","4,996","6,360","23,780","13,656","122,548","173,378","1,469","424","2,208","4,364","4,504","499","23,685","37,154","210,532"  ],
    ["California","5,254","1,518","8,253","12,647","24,037","15,080","82,233","149,022","9,671","9,283","25,149","30,758","27,593","644","142,263","245,361","394,383"  ],
]

Clearly, something needed done, so I wrote a small processing utility and JSON.stringify’d it:

var ddt = [];
for (var i = 0; i < states.length; i++) {
    var abvr = StateAbvrFromName(states[i][0]); // since data shows state name and jqvmap uses state code, il, ca, etc
    ddt[ddt.length] = {
        'State': { 'Name' : states[i][0], 'Code': abvr },
        'Rural': {
            'Interstate': parseInt(states[i][1].replace(/,/g, ""), 10),
            'Other_Freeways_Expressways': parseInt(states[i][2].replace(/,/g, ""), 10),
            'Other_Principal_Arterial': parseInt(states[i][3].replace(/,/g, ""), 10),
            'Minor_Arterial': parseInt(states[i][4].replace(/,/g, ""), 10),
            'Major_Collector':parseInt(states[i][5].replace(/,/g, ""), 10),
            'Minor_Collector_2': parseInt(states[i][6].replace(/,/g, ""), 10),
            'Local_2': parseInt(states[i][7].replace(/,/g, ""), 10),
            'Total': parseInt(states[i][8].replace(/,/g, ""), 10),
        },
        'Urban': {
            'Interstate': parseInt(states[i][9].replace(/,/g, ""), 10),
            'Other_Freeways_Expressways': parseInt(states[i][10].replace(/,/g, ""), 10),
            'Other_Principal_Arterial': parseInt(states[i][11].replace(/,/g, ""), 10),
            'Minor_Arterial': parseInt(states[i][12].replace(/,/g, ""), 10),
            'Major_Collector': parseInt(states[i][13].replace(/,/g, ""), 10),
            'Minor_Collector_2': parseInt(states[i][14].replace(/,/g, ""), 10),
            'Local_2': parseInt(states[i][15].replace(/,/g, ""), 10),
            'Total': parseInt(states[i][16].replace(/,/g, ""), 10),
        },
        'Total' : parseInt(states[i][17].replace(/,/g, ""), 10),
    };
}

Throwing It All Together

Going in to this little project, I knew that I wanted to run without any server side code, I wanted users to be able to minipulate the data to change the map, and I knew I wanted it to be as light weight as possible. I didn’t want any node modules or components or any ‘build’ time tooling to be required to make this work.

I opted to use some jQuery event handling to glue everything together, and I’m actually happy with how it worked out.

How can I set my IdentityServer4 BackChannelHandler from within an xUnit integration test using WebApplicationFactory?

Someone asked on Stack Overflow:

Update: After correcting the certificate issue, I’m now getting a 500 response form the test, with this message:

InvalidOperationException: IDX20803: Unable to obtain configuration from: ‘http://localhost/.well-known/openid-configuration’.

That appears to be similar to this issue: https://github.com/IdentityServer/IdentityServer4/issues/685; however, I can’t come up with a way to set the backchannel client or handler from my test — it seems like a chicken and egg situation.


This issue was fixed by using a real certificate/.pfx file. That lead to the above issue.

I’m using WebApplicationFactory to do integration tests over my API, and I think I’ve covered all the bases with getting the http clients configured correctly. I’m getting an error when calling an action in my API.

This is the error when executing a get against the api with a token:

WWW-Authenticate: Bearer error=“invalid_token”, error_description=“The signature key was not found”

Here’s a simple test class that demonstrates this problem:

public class EntityControllerShould : IClassFixture<WebApplicationFactory<Startup>>
{
    private readonly WebApplicationFactory<Startup> _factory;

    public EntityControllerShould(WebApplicationFactory<Startup> factory)
    {
        _factory = factory;
    }

    [Fact]
    public async Task ReturnListOfEntities_ForGet()
    {
        // arrange
        _factory.CreateClient();

        var handler = _factory.Server.CreateHandler();

        var client = new HttpClient(handler) { BaseAddress = new System.Uri("http://localhost/") };

        // discover endpoints from metadata
        var dc = new DiscoveryClient(client.BaseAddress.ToString(), handler);
        var disco = await dc.GetAsync();
        if (disco.IsError)
        {
            Assert.True(false);
        }
        // request token
        var tokenClient = new TokenClient(disco.TokenEndpoint, "api_client", "secret", handler);
        var tokenResponse = await tokenClient.RequestClientCredentialsAsync("api1");

        if (tokenResponse.IsError)
        {
            Assert.True(false);
        }

        client.SetBearerToken(tokenResponse.AccessToken);

        // act
        var response = await client.GetAsync("api/entity/?id=123");
        // response code is 401 with the above quoted error in the header
        response.EnsureSuccessStatusCode();

        var responseString = await response.Content.ReadAsStringAsync();

        // assert
        Assert.NotNull(responseString);
    }
}

Snip from Startup.cs in the API project:

services.AddIdentityServer()
            .AddSigningCredential(myCertificate)
            .AddSigningCredential()
            .AddClientStore<CustomClientStore>()
            .AddInMemoryIdentityResources(IdentityServerConfig.IdentityResources)
            .AddInMemoryApiResources(IdentityServerConfig.Apis);
  • I am hosting the IdentityServer4 and the API in the same project.
  • When I manually perform integration tests, through a browser, it works just fine
  • I have found this which seems very similar

Is there something I need to account for when running in the context of an xunit test that I am not?

I posted the following answer, which was chosen as the accepted answer and received 1 upvote:

The only solution I’ve come up with, is to setup a static Handler on the Startup class of the API project and then override it from within each unit test.

Specifically:

// startup.cs
public static HttpMessageHandler Handler { get; set; }

// snip from configureservices
.AddJwtBearer(jwt =>
 {
      // defaults as they were
      jwt.Authority = "http://localhost:5000/";
      jwt.RequireHttpsMetadata = false;
      jwt.Audience = "api1";
      // if static handler is null don't change anything, otherwise assume integration test.
      if(Handler == null)
      {
          jwt.BackchannelHttpHandler = Handler;
          jwt.Authority = "http://localhost/";
      }
  });

Complete listing from IdSvrAndApi project:

 public class Startup
 {
     public Startup(IConfiguration configuration)
     {
         Configuration = configuration;
     }

     public IConfiguration Configuration { get; }
     public static HttpMessageHandler Handler { get; set; }

     public void ConfigureServices(IServiceCollection services)
     {
         services.AddMvc();

         services.AddIdentityServer()
             .AddDeveloperSigningCredential()
             .AddInMemoryIdentityResources(Config.IdentityResources)
             .AddInMemoryClients(Config.Clients)
             .AddInMemoryApiResources(Config.Apis)
             .AddTestUsers(TestUsers.Users);

        services.AddAuthentication()
           .AddJwtBearer(jwt =>
           {
               jwt.BackchannelHttpHandler = Handler;
               jwt.Authority = "http://localhost/";
               jwt.RequireHttpsMetadata = false;
               jwt.Audience = "api1";
           });
            .AddJwtBearer(jwt =>
            {
                // defaults as they were
                jwt.Authority = "http://localhost:5000/";
                jwt.RequireHttpsMetadata = false;
                jwt.Audience = "api1";
                // if static handler is null don't change anything, otherwise assume integration test.
                if(Handler == null)
                {
                    jwt.BackchannelHttpHandler = Handler;
                    jwt.Authority = "http://localhost/";
                }
            });
    }

A fully working sample of this can be seen here: https://github.com/fuzzzerd/IdentityServerAndApi.

I have not received a definitive answer on if this is the recommended way to acheive this, but I did open an issue on the project here: https://github.com/IdentityServer/IdentityServer4/issues/2877


Originally posted on Stack Overflow — 1 upvotes (accepted answer). Licensed under CC BY-SA.

My Great Grandma's Buttermilk Pancakes

The ingredients:

  • 2 cups flour
  • 2 tsp baking powder
  • 1 tsp salt
  • 1/2 tsp baking soda
  • 3 Tbs sugar
  • 2 eggs, separated
  • 2 cups buttermilk (or more)
  • 1/4 cup melted butter

Sift flour, measure and re-sift with other dry ingredients. Combine beaten yolks with buttermilk and add to dry ingredients. Add melted butter. Beat egg whites until stiff and fold into mixture. Bake on hot waffle iron or make into pancakes.

When a Difference In Your Environment Make a Difference

I’m using IdentityServer4 for a couple projects. Its great, and might warrant a post of its own; however, one thing I’ve been struggling with is loading the jwt signing certificates. I’ve been using the powershell cmdlet New-SelfSignedCertificate to generate the pfx files and it works great on my local computer.

Running this on a web server has caused some grief, but lead to my learning a bit more about how these things actually work.

This is the final code that works, but I’ll walk through how I got to it.

new X509Certificate2(keyFilePath, keyFilePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.EphemeralKeySet)​

The first thing is that the certificate file itself can have indicators stating whether to load to User store or Machine store; so I’ve used MachineKeySet to ensure we override that.

Additionally I’m also specifying EphemeralKeySet, which indicates the private keys should not be persisted anywhere. This is the key part that allows everything to work when running as ApplicationPoolIdentity on a server without administrative privileges.

Without passing the additional Storage Flags, the system uses whats in the certificate file/data and that works locally since I have a user profile and/or administrative rights. By default, IIS does NOT load the user profile which means no environment variables or user certificate store. In order to use MachineKeySet you need administrative privileges (something your web facing accounts should not have) so that’s where Ephemeral comes in to play. Nothing is persisted so the admin rights are not needed. There are some incompatibilities with this approach; noted in the sources below, but for jwt signing it works.

For reference and searches, here are the errors I got/overcame.

Using default constructor without flags:

Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: The system cannot find the file specified

Specifying only MachineKeySet, while running as ApplicationPoolIdentity:

Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Access denied

Relevant sources:

Model becomes null when any of the parameters is null

Someone asked on Stack Overflow:

In my Angular 5 application, I would like to save an “event” object with the following method :

save(newEvent: NewEvent): Observable<any> {
    const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json' }) };
    const requestUrl = 'api/event';
    return this.http.post<any>(requestUrl, newEvent, httpOptions);
  }

The NewEvent model is :

export class NewEvent {
  id: number;
  title: string;...

  constructor() {
    this.id = null;
    this.title = '';...
  }
}

And after I call this with a method in a controller with .NET Core :

[HttpPost("api/event")]
public IDictionary<string, Object> SaveEvent([FromBody] EventViewModel model){...}

The EventViewModel POCO is :

{
    public class EventViewModel
    {
        public int Id { get; set; }
        public string Title { get; set; }...
    }
}

When my object EventViewModel has no attributes with a “null” value it works with no problems, but when I have “null” attributes it doesn’t work (the EventViewModel became “null”) and I want to have sometimes “null” attributes.

I posted the following answer, which was chosen as the accepted answer and received 2 upvotes:

Your C# model has a non-nullable int for the Id column. If you want it to be nullable (as you set it to null in your javascript model) you should define it as int? or Nullable<int>.

See also: Nullable Types.


Originally posted on Stack Overflow — 2 upvotes (accepted answer). Licensed under CC BY-SA.

NewsAPI C# library runs on console, hangs on winforms

Someone asked on Stack Overflow:

I ran the example given at the web site under Visual Studio 2017 Community Edition and it worked fine. However, when I attempted to run it on a winforms library, it hung, even when given the exact same term:

Console Version

static void Main(string[] args)
{
    var newsApiClient = new NewsApiClient("KeyRedacted");
    var articlesResponse = newsApiClient.GetEverything(new EverythingRequest
    {
        Q = "Apple",
        SortBy = SortBys.Popularity,
        Language = Languages.EN,
        From = new DateTime(2018, 10, 16)
    });
    if (articlesResponse.Status == Statuses.Ok)
    {

    //code here

Winforms Version

private void btnSearch_Click(object sender, EventArgs e)
{
    var newsApiClient = new NewsApiClient("keyredacted");
    var articleResponse = newsApiClient.GetEverything(new EverythingRequest
    {
        Q = "Apple",
        SortBy = SortBys.Popularity,
        Language = Languages.EN,
        From = new DateTime(2018, 10, 16)
    });  //this is where it hangs

    if (articleResponse.Status == Statuses.Ok)
    {

I posted the following answer, which was chosen as the accepted answer and received 1 upvote:

Assuming that you’re using this client, the method you’re calling uses a Task.Result which can cause a deadlock. Seems reasonable, since the code/signature and examples match.

I would rewrite your code like this for WinForms:

private async void btnSearch_Click(object sender, EventArgs e)
{
    var newsApiClient = new NewsApiClient("keyredacted");
    var articleResponse = await newsApiClient.GetEverythingAsync(new EverythingRequest
    ...

If you are deadset on not using the async methods in your code you could try running it inside of a Task.Run(() => /* stuff */);

See also: https://blogs.msdn.microsoft.com/pfxteam/2012/04/13/should-i-expose-synchronous-wrappers-for-asynchronous-methods/


Originally posted on Stack Overflow — 1 upvotes (accepted answer). Licensed under CC BY-SA.

What is the difference between UseHttpsRedirection and UseHsts

Someone asked on Stack Overflow:

I don’t quite get the difference between UseHsts and UseHttpsRedirection in the configure section of the startup file in .net core. Could anyone explain?

I posted the following answer, which was chosen as the accepted answer and received 49 upvotes:

According to the documentation you should use both together:

We recommend all production ASP.NET Core web apps call:

  • The HTTPS Redirection Middleware (UseHttpsRedirection) to redirect all HTTP requests to HTTPS.
  • UseHsts, HTTP Strict Transport Security Protocol (HSTS).

ASP.NET Core Enforce HTTPS

The .UseHttpsRedirection() will issue HTTP response codes redirecting from http to https. The .UseHsts() will add the HSTS response header which the client is supposed to obey.

Notable comments

Nate (2 upvotes): They do not block incoming requests. UseHttpsRedirection should issue a redirect from http to https. UseHsts is a header to remind the browser that when they come back to this site, skip the initial http request, and go directly to https. If you want to block http completely, you’d need to do that on your host (iis, apache, etc).


Originally posted on Stack Overflow — 49 upvotes (accepted answer). Licensed under CC BY-SA.

Introducing my latest side project - FMData

I switched jobs in March of this year, that is a story for a different time, but the important thing is that it reintegrated me with some technology I had not used in quite some time: FileMaker. FileMaker is a database system that provides UI and basic scripting capabilities all in a single package. Users use the FileMaker client to access data stored in FileMaker databases, utilizing layouts and scripts in the database. Its an all in one system.

As a web developer with a lot of C# code under my belt, I wanted to connect to data in FileMaker from the outside. Historically the way to do this was through their XML Publishing Engine, I picked up an existing open source project and modified it to suit my needs. Ten years ago, this was a great solution and it worked well. It still does, but as things change so must we. In FileMaker 17 the Data API was introduced. It uses JSON and is RESTful. A new package was needed. Enter my side project: FMData. I built this as a learning exercise, but quickly realized it could be useful to other developers.

The library provides coverage for the FileMaker 17 Data API, and I’ve just released v2.1, cleaning up a handful of bugs and improving coverage of the underlying FileMaker API. I still don’t have full coverage, but I’m inching towards it. I have tons of ideas for features and enhancements, so be sure to keep an eye on the project. If you find it useful let me know. If you find a bug, open an issue. If you have a feature idea, open an issue on github and consider making a pull request.

The package is available on Nuget, and getting some data is really this simple:

var client = new FileMakerRestClient("server", "fileName", "user", "pass"); // without .fmp12
var toFind = new Model { Name = "someName" };
var results = await client.FindAsync(toFind);
// results = IEnumerable<Model> matching with Name field matching "someName" as a FileMaker Findrequest.

That’s all there is to it, and there’s more examples on the project site: https://fmdata.io/

Breakpoints are not hit while debugging xunit test that includes a large string

Someone asked on Stack Overflow:

I have a test that uses some Base64 encoded strings as parameters to a method. The test runs and passes (or fails if I modify the method to a failed state). The point is that the test framework executes as expected.

When I try to debug the test through Visual Studio (or VSCode) the debugger starts, loads symbols, and then exits with my test case showing a passing state. No Breakpoints are hit.

I only identified this large string by trial an error, removing one test case at a time until I was able to successfully hit breakpoints.

This method reproduces the problem. Even though its not used, comment out b64 and you should be able to hit breakpoints through the debugger, uncomment it and breakpoints fail.

This happens with xunit 2.3.1 and 2.4.0; not sure if its even an xuint thing, but I’m trying to figure out what I can do to debug this method.

Run dotnet new xunit and drop this test in: https://gist.github.com/fuzzzerd/8347a8609fd1ccabdfaeea564d42a976 (snip is too large for question body)

I posted the following answer, which was chosen as the accepted answer:

Looks like I’m running into this issue: https://github.com/dotnet/roslyn/issues/20118. There’s no work around posted, but loading from a file does successfully work around this issue.


Originally posted on Stack Overflow — 0 upvotes (accepted answer). Licensed under CC BY-SA.

signed letter b

Dad. Geek. Gamer. Software developer. Cloud user. Old Car enthusiast.  Blogger.


Top Posts


profile for Nate on Stack Exchange, a network of free, community-driven Q&A sites
a proud member of the blue team of 512KB club
Thoughts, opinions, and ideas shared here are my own. © 2026 Nate Bross.