stephenloggedon

stephenloggedon

Hello

I’m trying to learn some basic Phoenix stuff by writing a backend API and I am having trouble implementing client auth via mTLS. Maybe I am missing something about how mTLS works, but I can’t manage to force the server to authenticate the client. Is it actually possible to force the client to provide a cert to establish a connection?

I’m just using self signed certs, by the way.

Showing Posts 1 to 9

voltone

voltone

The server can request that the client provide a certificate. The client can choose to submit a certificate as part of the handshake in response to such a request, but it will never send a certificate if the server didn’t ask for it.

Some servers terminate the TLS handshake if the client did not provide a valid certificate, others allow the handshake to continue and return an error in a higher protocol layer (e.g. return a 403 HTTP response).

It is not clear from your question whether the Phoenix app is the server or the client, and what is on the other end.

Keep in mind that convincing Erlang’s ssl module to accept self-signed certificates requires customising the verification logic, as by default it will want to check the certificate against a set of trusted CAs instead.

stephenloggedon

stephenloggedon OP

Thanks for the response. To clarify, the Phoenix app is the server. Either terminating behavior is fine for now, but I am not sure what Phoenix is capable of out of the box. I am not quite sure how to extract the client certificate information after a connection is established to determine that a 403 should be returned. Maybe I could write a Plug for it? Terminating the handshake seems easier. In trying to set this up, I didn’t see anything in the documentation that suggested how to do this, but I could have missed it if either behavior is indeed supported.

tangui

tangui

If you’re thinking about RFC8705 the plug already exists: APIacAuthMTLS :wink:

voltone

voltone

Terminating the handshake is easier and it is the default when enabling mTLS for a Phoenix server by setting verify: :verify_peer in the Endpoint options.

If you need help setting those options I think you’re going to have to share with us what you’ve tried so far, what you are using as a client and what that client is telling you…

stephenloggedon

stephenloggedon OP

Here is what my endpoint config looks like.

config :phx_rest, PhxRestWeb.Endpoint,
  http: [port: 4000],
  https: [
    ip: :loopback,
    port: 4001,
    cipher_suite: :strong,
    keyfile: "/path/to/key.pem",
    certfile: "/path/to/cert.pem"
  ],
  verify: :verify_peer,
  force_ssl: [hsts: true],
  check_origin: false,
  code_reloader: true,
  debug_errors: true,
  secret_key_base: "secretkeybase",
  watchers: []

If I simply run curl http://localhost:4000 I get a successful response back. That is a little bit of an aside since I thought that the server should be forcing ssl with the hsts option, but I can simply remove the http endpoint altogether if I want. A more direct example of what is making me scratch my head is curl -k https://localhost:4001 is returning a successful response.

A side-note on HSTS: looking at the response headers does not show that HSTS is enabled.

LostKobrakai

LostKobrakai

You also need :fail_if_no_peer_cert set to true. It defaults to false.

voltone

voltone

The verify: :verify_peer option is an HTTPS listener option, so you’ll need to move it into the https section. You’ll also have to specify the cacerts or cacertfile (on newer OTP versions you can use client_cacerts or client_cafile instead to specifically define client certificate CAs).

As I said, self-signed certs are not going to work out of the box: you would have to define how the server is supposed to know which self-signed certificates to accept and which ones to reject.

HSTS header are not sent on localhost responses, as you may want to do other testing on localhost with a different app/stack with the same browser.

voltone

voltone

Oops, so I lied when I said…

Terminating the handshake is easier and it is the default when enabling mTLS for a Phoenix server

Thanks for the correction!

stephenloggedon

stephenloggedon OP

This was definitely my first inclination, but Bandit is rejecting this option. Those options are piped through to Bandit, correct?

** (Mix) Could not start application phx_rest: PhxRest.Application.start(:normal, []) returned an error: shutdown: failed to start child: PhxRestWeb.Endpoint
    ** (EXIT) shutdown: failed to start child: {PhxRestWeb.Endpoint, :https}
        ** (EXIT) an exception was raised:
            ** (RuntimeError) Unsupported key(s) in top level config: [:verify]
                (bandit 1.5.3) lib/bandit.ex:354: Bandit.validate_options/3
                (bandit 1.5.3) lib/bandit.ex:233: Bandit.start_link/1
                (stdlib 5.2.3) supervisor.erl:420: :supervisor.do_start_child_i/3
                (stdlib 5.2.3) supervisor.erl:406: :supervisor.do_start_child/2
                (stdlib 5.2.3) supervisor.erl:390: anonymous fn/3 in :supervisor.start_children/2
                (stdlib 5.2.3) supervisor.erl:1258: :supervisor.children_map/4
                (stdlib 5.2.3) supervisor.erl:350: :supervisor.init_children/2
                (stdlib 5.2.3) gen_server.erl:980: :gen_server.init_it/2
                (stdlib 5.2.3) gen_server.erl:935: :gen_server.init_it/6
                (stdlib 5.2.3) proc_lib.erl:241: :proc_lib.init_p_do_apply/3

However, it is working with the Cowboy adapter! Thanks for the help on this.

— All posts loaded —

Where Next? Top

Trending in Questions Top

water
I’m aware of 2 such projects, are there others? git: GitHub - team-alembic/realworld: A fullstack Phoenix LiveView application with back...
New
katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
peck
Hi everyone. My team and I have been working on a fairly modest app based around video streaming and chat, but we’ve landed a customer t...
New
bradley
I really like the adapter patterns that ecto, nebulex, waffle, etc. use and would love find something similar for a key management servic...
New
unaware8150
Hello folks! So at work, we are seeing some situations where we have to define some “fixed” strings that are used across the codebase in...
New
Alvinkariuki
How Can I Optimise Compile Time Dependencies I have been building an elixir application for about 2 years now. Many modules and files ha...
New
leoschweizer
Hi, we run different LLM models across a cluster, with each node loading a configurable subset. Model-specific queues let nodes consume ...
New

Other Trending Topics Top

budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
juhalehtonen
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New
budgie
I love Elixir. It’s one of 2 programming languages I’ve ever fallen in love with. But I don’t use it anymore. Serverless was the promis...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews