OAuth 2.0 and OpenId Connect

4/5/2022

By: Shaun Walker

Externalizing the authentication for your site has a number of key benefits. It allows users to identify themselves across websites and apps without having to manage a local password for each site. In addition, utilizing a trusted identity provider is a good general security practice as the fewer people that have access to your login information, the better. It also provides the opportunity for single sign-on across multiple sites and can be used to federate security with third party services and APIs.

Oqtane 3.1 adds support for integrating with an OAuth 2.0 or OpenID Connect provider - both of which are international standards that are widely used for enterprise IT security. OAuth 2.0 is a framework that controls authorization to protected resources such as applications or websites. OpenID Connect is an industry standard for federated authentication that is built on top of the OAuth 2.0 protocol and is specifically focused on user authentication. The 3.1 release provides the ability to customize the External Login criteria per site.

OAuth 2.0 and OpenId Connect

It is important to note that External Login providers are for authentication purposes only. The External Login provider must provide a valid email address for the signed in user, which will will be mapped to a local user in the site. The local user will be assigned to roles to provide them with permissions on the site. Note that it is possible to have External Login enabled while still providing the ability for a user to login using a local account (this capability can be disabled as well).

Note that OpenID Connect is the preferred approach for remote authentication... however not all services are providing an OpenID Connect endpoint yet. However OpenID Connect is based on OAuth 2.0 - it just layers on an additional ID token to standardize areas that OAuth 2.0 leaves up to choice, such as scopes and endpoint discovery. So it is possible to use standard OAuth 2.0 for authentication - you just need to provide the 3 required Urls - auth url, token url, and user info url (and client id and secret). A good example of a service which does not yet support OpenID Connect is Github.

In terms of authorization, Oqtanes uses a BFF architecture outlined in more detail in this blog which relies on same site cookies. This works well for the main web client use case with APIs as part of the same domain. However there are other use cases to consider as well.

For the use case of an external client application which wants to connect to the Oqtane API, a Jwt authentication capability is now possible. A site administrator can configure their Jwt token details and generate a long-lived token which can be used to access the API.

Token

Another use case is allowing the Oqtane web client to call remote API services which do not live in the same domain (ie. micro-services). A RemoteServiceBase class has been added which can be used by Razor components to make remote API calls (the RemoteServiceBase uses the IHttpClientFactory to construct a client which has the auth token already configured).

namespace Sample.DownstreamAPI.Services
{
    public class WeatherForecastService : RemoteServiceBase, IWeatherForecastService, IService
    {
        public WeatherForecastService(IHttpClientFactory httpClientFactory, SiteState siteState) : base(httpClientFactory, siteState) { }

        public async Task> GetWeatherForecastsAsync()
        {
            return await GetJsonAsync>("https://www.downstreamapi.com/weatherforecast");
        }
    }
}

The remote API would simply need to use the standard AddJwtBearer() method in its Startup class to validate the token and provide secure access to its API methods.

builder.Services.AddAuthentication(options => {
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(options => {
        options.RequireHttpsMetadata = false;
        options.SaveToken = true;
        options.TokenValidationParameters = new TokenValidationParameters()
        {
            ValidateIssuerSigningKey = true,
            ValidateIssuer = true,
            IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes("your secret key")),
            ValidIssuer = "http://localhost:44357",
            ValidateAudience = false,
            ValidateLifetime = true,
            ClockSkew = TimeSpan.FromDays(1)
        };
    });

Standard auth attributes can be used in API controllers based on the roles assigned in Oqtane:

    [HttpGet]
    [Authorize(Roles = "Administrators")
    public IEnumerable Get()
    {
        // your logic
    }


Do You Want To Be Notified When Blogs Are Published?
RSS