You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于SSL verify_fun中UserState变量及Cowboy证书存储的技术问询

Certificate Pinning & Passing Cert Info via UserState in Cowboy

Great question! I’ve dealt with this exact scenario when setting up mutual TLS in Cowboy, so let’s break down your options clearly.

Option 1: Using UserState to Pass Cert Info

You absolutely can use the UserState parameter in verify_fun to store certificate details and retrieve them later in your Cowboy server. Here’s how it works:

  • The UserState is an arbitrary term you can initialize (e.g., an empty map) when configuring your TLS listener.
  • During the certificate verification process in verify_fun, you can extract the data you need (like subject DN, public key, or custom extensions) from the client certificate, update the UserState with this data, and return it alongside the valid status.
  • Once verification passes, Cowboy stores this updated UserState in the request’s metadata, which you can access in your request handlers.

Example Code Snippet

First, define your verify_fun to extract and store cert info:

verify_fun(Cert, _Event, UserState) ->
    % Decode the certificate to extract fields
    OtpCert = public_key:pkix_decode_cert(Cert, otp),
    SubjectDN = OtpCert#'OTPCertificate'.tbsCertificate#'OTPTBSCertificate'.subject,
    PublicKey = OtpCert#'OTPCertificate'.tbsCertificate#'OTPTBSCertificate'.subjectPublicKeyInfo,
    
    % Update UserState with the extracted data
    UpdatedState = maps:merge(UserState, #{
        cert_subject => SubjectDN,
        cert_public_key => PublicKey
    }),
    {valid, UpdatedState}.

Then, configure your Cowboy listener to use this verify_fun and initialize UserState:

start() ->
    SslOpts = [
        {certfile, "path/to/server.crt"},
        {keyfile, "path/to/server.key"},
        {verify, verify_peer},
        {fail_if_no_peer_cert, true},
        {verify_fun, {fun verify_fun/3, #{}}} % Initialize with empty map
    ],
    cowboy:start_tls(https_listener, SslOpts, #{env => #{dispatch => dispatch()}}).

Finally, retrieve the UserState in your request handler:

init(Req0, State) ->
    % Fetch the updated UserState from request metadata
    case cowboy_req:meta(ssl_verify_user_state, Req0) of
        undefined ->
            % Handle unexpected case where verification didn't run
            Req = cowboy_req:reply(500, #{}, "Internal error", Req0),
            {ok, Req, State};
        CertData ->
            % Use CertData for client authentication logic
            io:format("Client cert subject: ~p~n", [maps:get(cert_subject, CertData)]),
            Req = cowboy_req:reply(200, #{}, "Authenticated", Req0),
            {ok, Req, State}
    end.

Option 2: Directly Fetching Cert Info in Cowboy Handlers

If you don’t need to tie the cert data extraction to the verification process, you can skip modifying verify_fun entirely and fetch the client certificate directly in your request handlers using cowboy_req:peer_cert/1.

Example Code Snippet

init(Req0, State) ->
    case cowboy_req:peer_cert(Req0) of
        {ok, Cert} ->
            % Decode and extract the info you need
            OtpCert = public_key:pkix_decode_cert(Cert, otp),
            SubjectDN = OtpCert#'OTPCertificate'.tbsCertificate#'OTPTBSCertificate'.subject,
            
            % Proceed with authentication using SubjectDN
            Req = cowboy_req:reply(200, #{}, "Authenticated", Req0),
            {ok, Req, State};
        undefined ->
            % No client certificate provided
            Req = cowboy_req:reply(401, #{}, "Client certificate required", Req0),
            {ok, Req, State}
    end.

Which Approach Should You Use?

  • Use UserState if:
    • You need to validate specific cert fields during the verification process (e.g., checking if the subject matches an allowed list) and want to pass the validated data forward.
    • You want to avoid re-decoding the certificate multiple times (since you already process it in verify_fun).
  • Use direct peer_cert fetch if:
    • Your certificate verification is handled by standard CA checks (no custom verify_fun logic).
    • You only need cert info for post-verification authentication (like checking if the subject is in a database) and prefer simpler, more focused code.

Both methods are fully supported by Cowboy—pick the one that aligns with your workflow!

内容的提问来源于stack exchange,提问作者ITChap

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:27:08