Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Base path configuration #87

Merged
merged 5 commits into from
Aug 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,13 @@ There are two ways to provide configuration for supported scopes, clients and us
* `API_RESOURCES_PATH`
* `IDENTITY_RESOURCES_PATH`


## Base path

The server can be configured to run with base path. So all the server endpoints will be also available with some prefix segment.
For example `http://localhost:8080/my-base-path/.well-known/openid-configuration` and `http://localhost:8080/my-base-path/connect/token`.
Just set `BasePath` property in `ASPNET_SERVICES_OPTIONS_INLINE/PATH` env var.

## Custom endpoints

### User management
Expand Down
2 changes: 2 additions & 0 deletions e2e/.env
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ OIDC_USERINFO_URL=http://localhost:8080/connect/userinfo
OIDC_GRANTS_URL=http://localhost:8080/grants
OIDC_DISCOVERY_ENDPOINT_HTTPS=https://localhost:8443/.well-known/openid-configuration
OIDC_MANAGE_USERS_URL=http://localhost:8080/api/v1/user
OIDC_DISCOVERY_ENDPOINT_WITH_BASE_PATH=http://localhost:8080/some-base-path/.well-known/openid-configuration
OIDC_TOKEN_URL_WITH_BASE_PATH=http://localhost:8080/some-base-path/connect/token
3 changes: 2 additions & 1 deletion e2e/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
"unicorn/numeric-separators-style": "off",
"unicorn/prevent-abbreviations": ["error", {
"checkFilenames": false
}]
}],
"unicorn/prefer-node-protocol": "off"
},
"overrides": [
{
Expand Down
4 changes: 4 additions & 0 deletions e2e/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ services:
USERS_CONFIGURATION_PATH: /config/user-configuration.json
CLIENTS_CONFIGURATION_PATH: /config/clients-configuration.json
IDENTITY_RESOURCES_PATH: /config/identity-resources.json
ASPNET_SERVICES_OPTIONS_INLINE: |
{
"BasePath": "/some-base-path"
}
volumes:
- ./config:/config:ro
- ./https:/https:ro
Expand Down
33 changes: 33 additions & 0 deletions e2e/tests/base-path.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as querystring from 'querystring';
import * as dotenv from 'dotenv';
import axios from 'axios';

import clients from '../config/clients-configuration.json';
import type { Client } from '../types';

describe('Base path', () => {
let client: Client;

beforeAll(() => {
dotenv.config();
client = clients.find(c => c.ClientId === 'client-credentials-flow-client-id');
expect(client).toBeDefined();
});

test('Discovery Endpoint', async () => {
const response = await axios.get(process.env.OIDC_DISCOVERY_ENDPOINT_WITH_BASE_PATH);
expect(response.data.token_endpoint).toEqual(process.env.OIDC_TOKEN_URL_WITH_BASE_PATH);
});

test('Token Endpoint', async () => {
const parameters = {
client_id: client.ClientId,
client_secret: client.ClientSecrets?.[0],
grant_type: 'client_credentials',
scope: client.AllowedScopes.join(' '),
};

const response = await axios.post(process.env.OIDC_TOKEN_URL_WITH_BASE_PATH, querystring.stringify(parameters));
expect(response).toBeDefined();
});
});
4 changes: 3 additions & 1 deletion src/Helpers/AspNetServicesHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public class AspNetServicesOptions
public SessionOptions Session { get; set; }

public ForwardedHeadersOptions ForwardedHeadersOptions { get; set; }

public string BasePath { get; set; }
}

public class AuthenticationOptions
Expand Down Expand Up @@ -82,4 +84,4 @@ private static void ConfigureCors(IServiceCollection services, AspNetCorsOptions
);
}
}
}
}
33 changes: 33 additions & 0 deletions src/Middlewares/BasePathMiddleware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using IdentityServer4.Extensions;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;
using IdentityServer4.Configuration;

#pragma warning disable 1591

namespace OpenIdConnectServer.Middlewares
{
public class BasePathMiddleware
{
private readonly RequestDelegate _next;
private readonly IdentityServerOptions _options;

public BasePathMiddleware(RequestDelegate next, IdentityServerOptions options)
{
_next = next;
_options = options;
}

public async Task Invoke(HttpContext context)
{
var basePath = Config.GetAspNetServicesOptions().BasePath;
var request = context.Request;
if(request.Path.Value.Length > basePath.Length)
{
request.Path = request.Path.Value.Substring(basePath.Length);
context.SetIdentityServerBasePath(basePath);
}
await _next(context);
}
}
}
14 changes: 13 additions & 1 deletion src/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
using OpenIdConnectServer.Validation;
using OpenIdConnectServer.JsonConverters;
using Newtonsoft.Json.Serialization;
using OpenIdConnectServer.Middlewares;
using IdentityServer4.Hosting;

namespace OpenIdConnectServer
{
public class Startup
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
Expand Down Expand Up @@ -52,6 +54,16 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
AspNetServicesHelper.UseAspNetServices(app, aspNetServicesOptions);

app.UseIdentityServer();

var basePath = Config.GetAspNetServicesOptions().BasePath;
if (!string.IsNullOrEmpty(basePath))
{
app.UseWhen(ctx => ctx.Request.Path.StartsWithSegments(basePath), appBuilder => {
appBuilder.UseMiddleware<BasePathMiddleware>();
appBuilder.UseMiddleware<IdentityServerMiddleware>();
});
}

app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
Expand Down