iframe Security is So Strange

As I write, this is the attribute soup on an <iframe> on CodePen in order to dial in the right combination of security and usability:


sandbox=”allow-downloads allow-forms allow-modals allow-pointer-lock allow-popups allow-presentation allow-same-origin allow-scripts allow-top-navigation-by-user-activation”

allow=”accelerometer; camera; encrypted-media; display-capture; geolocation; gyroscope; microphone; midi; clipboard-read; clipboard-write; web-share”



Wow! I think that’s an awful lot of detailed HTML to get right. If any little bit of that was wrong, we’d hear about it here at CodePen right away. It would break what users expect to work.

To compound this issue, the above code is just the output for Chrome-n-friends. Both Safari and Firefox need variations of this HTML to perfect. That puts us in UA-sniffing territory, which is never a particularly happy place.

Add extra attributes or values to this code, you might make annoying extra console noise — quite annoying in an app for developers. Skip them, and you cripple the app itself. We have no choice but to render user code in an <iframe>, for all the obvious cross-origin security it provides.

Compounding things again, all this code changes. New features arrive in browsers that require new iframe permissions. But there is no good place to follow all the changes, so the way we tend to find out is when a user graciously sends in a support request for something that doesn’t work that they think should.

The code itself is just… strange! Why is sandbox space-separated but allow is semicolon-separated? Why are sandbox and allow different attributes at all? Especially when they are both whitelists? Why are some features their own special attributes?

Just feels like an awful lot of weirdness for one isolated purpose.

I was just looking over our setup here at CodePen and refactoring it a bit, and decided to chuck the attributes in JSON to maintain from there, so here’s a copy of that in case it’s useful to anyone else.

The post iframe Security is So Strange appeared first on CodePen Blog.

Flatlogic Admin Templates banner

Problems with online user authentication when using self sovereign identity

Using self sovereign identity (SSI), there is no standardized solutions for solving online user authentication when using verifiable credentials and verifying the identity and user. All solutions result in further compromises and result in new problems. To understand the problems, we need to understand how this works. The following diagram shows the verifiable credential (VC) relationship with Issuer, Holders (behind a software wallet) and the verifier. Trust between the actors and are you required to authenticate the user behind the wallet are key and important requirements for some systems. Verifiable credentials are not issued to a user but to a wallet representing the user.

Image src: Verifiable Credentials Data Model 1.0 specification 

Use case definition: The user must be authenticated and verified by the “verifier” application using the verifiable credential. Is the user data in the verifiable credential the same user presenting it or a user, application allowed to use the VC on behalf of that person. So how can this be solved?

Solution 1: User Authentication is on the wallet.

The wallet application implements the authentication of the user and binds the user to all credentials issued to the wallet through the agents and then sent to verifier applications. With BBS+ verifiable credentials, it is possible to do this. The wallet is responsible for authentication of the user, but this is not standardized, and no wallet does this the same. If the wallet is responsible for user authentication, then applications only need to authorize the verifiable credentials and not authenticate the user behind the wallet and represented in the verifiable credential which is connected to the wallet. The VC is invalid if a different wallet sends this. So the verifier applications only validates that the sender of the VC has possession of the credential, nothing else and trusts that the wallet authenticates the user correctly and also trusts that the wallet prevents misuse. The verifier cannot validate if the application, person using the credential is allowed to use it. The verifier must trust that the wallet does this correctly.

Problems with this solution:

Wallet Software monopoly: If a state body pushes this solution, then it has effectively created a monopoly for the producer of the wallet software. This is because at present with existing wallets, the required authentication is specific to the application and the definition of how this is required and the hardware device used for the wallet. No standards exist for how a user is authenticated in the wallet and what level of initial user authentication is required. This could be improved by creating a new standard for wallets which can be used by the state body and the way the wallet must authenticate the users of the wallet. Then any wallet which fulfills the standard can be used for state created verifiable credentials.

Backup and recovery of wallets becomes really complicated because the user is connected to the software wallet. If I lose my wallet, or would like to switch the wallet, a safe secure standardized way would be required proving that the wallet has authenticated the same person as the initial wallet or a person of trust. All issued credentials would probably need to be re-issued. The user of the wallet and the wallet instance are tightly coupled.

Verifier authorization only, not authentication: The verifier does not authenticate the user behind the wallet, just accepts that it was done correctly. This creates a closed system between the verifier and the wallet even though it is distributed. The verifier is tightly coupled in the relationship if blindly trusting verifiable credentials from wallets which are not in its system scope. If the verifier needs to verify the identity, then FIDO2, OIDC, OAUTH2, PKI or existing online verifying flows could be used as a second factor.

Single point of failure: if the credential issuer VCs can no longer be trusted, then all verifiers using the credentials need to revoke everything created from the VC . This is not a problem if the verifier authenticated it’s users, identities directly.

Solution 2: Use the OIDC SIOP standard to authenticate when issuing and verifying the verifiable credentials



A second way of solving user authentication in SSI is to use OpenID Connect and SIOP. The credential issuer uses it’s own OpenID Connect server with pre-registered users where the person has been correctly identified. The credential issuer is responsible for identifying and authenticating the identity, ie the user plus the application. Each credential type which is issued requires a specific OpenID Connect client. When the user, using the SIOP agent from his or her wallet tries to add a new verifiable credential using SIOP, the user is required to authenticate using the identity provider (IDP). This can also be used when verifying credentials. By using this, any wallet which supports the SIOP agent with the correct verifiable credential type used can work. The strong authentication is not required on the wallet because this is part of the flows and the user does not need to be connected to the wallet. If the verifier does not authenticate the user or application sending the verifiable credentials, then strong authentication would still be required on the wallet.

Problems with this solution:

Requires an OIDC server: All credential issuers require an OpenID Connect server and a separate client per credential type.

Verifier authorization only, not authentication: Only proof of possession on the verifier. Verifiers need to start an SIOP verification and the verifier needs to trust the OIDC server used for the client. The OIDC server authenticates and not the verifier.

Single point of failure: if the credential issuer VCs can no longer be trusted, then all verifiers using the credentials need to revoke everything created from the VC . This is not a problem if the verifier authenticated it’s users directly.

Solution 3: Verifiers authenticate the user correctly before trusting the verifiable credentials sent from an unspecific wallet.

Another way of solving this is that all credential issuers and all verifiers authenticate the user behind a verifiable credential using their own process. This avoids the single point of failure. Each sign-in would require an extra step to authenticate, if using SSI for example a FIDO2 key or a PKI authentication or some OIDC flow can be used. SSI could be used as the first factor in the application authentication. This solution works really good but a lot of the advantages of SSI is lost.

Problems with this solution:

All applications require authentication. This is more effort if implementing a closed system, but all applications need to do this anyway, so it’s not really a disadvantage. If you control both the issuer and the verifier, then the verifier application could just do authorization of the verifiable credential.

SSI adds little value. Due to the fact that a second authentication method is used everywhere, this would also work without SSI, so why add SSI then in the first place.


User authentication is not an easy problem to solve and SSI at present does not solve this in a standard way. All existing solutions do something vendor specific or solve this in a closed system. As soon as inter-op is required, then the problems begin. It is important to solve this in a way which does not require a vendor specific solution or creates a monopoly for a vendor solution. At present, SSI solutions still have very little convergence. We have different ledgers which only work with specific agents. We have different agents, SIOP, DIDComm V1, V2 which are only supported by certain wallets. We have different verifiable credentials standards which do not work together. We have no authentication standards on the wallets, no standard for backup and recovery. It is still not clear how the trust register for credentials issuers will work, I as an application verifier need an easy way to validate the quality of the credential issuer otherwise how can I know if the credential was issued in a good way without doing my own security check. Guardianship will also complicate the user authentication process.







Flatlogic Admin Templates banner

Implementing Basic Authentication in ASP.NET Core Minimal API

This post is about how implement basic authentication in ASP.NET Core Minimal API. Few days back I got a question / comment in the blog post about Minimal APIs – about implementing Basic authentication in Minimal APIs. Since the Action Filters support is not available in Minimal API I had to find some alternative approach for the implementation. I already wrote two blog posts Basic authentication middleware for ASP.NET 5 and Basic HTTP authentication in ASP.Net Web API on implementing Basic authentication. In this post I am implementing an AuthenticationHandler and using this for implementing basic authentication. As I already explained enough about the concepts, I am not discussing them again in this post.

Here is the implementation of the BasicAuthenticationHandler which implements the abstract class AuthenticationHandler.

public class BasicAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
public BasicAuthenticationHandler(
IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock
) : base(options, logger, encoder, clock)

protected override Task<AuthenticateResult> HandleAuthenticateAsync()
var authHeader = Request.Headers[“Authorization”].ToString();
if (authHeader != null && authHeader.StartsWith(“basic”, StringComparison.OrdinalIgnoreCase))
var token = authHeader.Substring(“Basic “.Length).Trim();
var credentialstring = Encoding.UTF8.GetString(Convert.FromBase64String(token));
var credentials = credentialstring.Split(‘:’);
if (credentials[0] == “admin” && credentials[1] == “admin”)
var claims = new[] { new Claim(“name”, credentials[0]), new Claim(ClaimTypes.Role, “Admin”) };
var identity = new ClaimsIdentity(claims, “Basic”);
var claimsPrincipal = new ClaimsPrincipal(identity);
return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(claimsPrincipal, Scheme.Name)));

Response.StatusCode = 401;
Response.Headers.Add(“WWW-Authenticate”, “Basic realm=”dotnetthoughts.net””);
return Task.FromResult(AuthenticateResult.Fail(“Invalid Authorization Header”));
Response.StatusCode = 401;
Response.Headers.Add(“WWW-Authenticate”, “Basic realm=”dotnetthoughts.net””);
return Task.FromResult(AuthenticateResult.Fail(“Invalid Authorization Header”));

Next modify the Program.cs like this.

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
.AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>
(“BasicAuthentication”, null);

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())


Now it is done. You can enable block the anonymous access by adding the authorize attribute to the method like this.

app.MapGet(“/weatherforecast”, [Authorize]() =>
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
Random.Shared.Next(-20, 55),
return forecast;

Now if you browse the Weather forecast endpoint – https://localhost:5001/weatherforecast, it will prompt for user name and password. Here is the screenshot of the app running on my machine.

Happy Programming 🙂

Flatlogic Admin Templates banner