-module(wisp_basic_auth). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/wisp_basic_auth.gleam"). -export([validate_basic_auth/4]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -file("src/wisp_basic_auth.gleam", 57). -spec encode_creds(binary(), binary()) -> binary(). encode_creds(Id, Secret) -> Expected_creds = <<<>/binary, Secret/binary>>, Encoded_creds = gleam_stdlib:base64_encode( gleam_stdlib:identity(Expected_creds), true ), <<"Basic "/utf8, Encoded_creds/binary>>. -file("src/wisp_basic_auth.gleam", 43). -spec check_authorization(binary(), list({binary(), binary()})) -> {ok, binary()} | {error, nil}. check_authorization(Authorization_header, Authorized) -> Match = fun(Auth) -> {Id, Password} = Auth, case encode_creds(Id, Password) =:= Authorization_header of true -> {ok, Id}; false -> {error, nil} end end, gleam@list:find_map(Authorized, Match). -file("src/wisp_basic_auth.gleam", 64). -spec unauthorized_response(binary()) -> gleam@http@response:response(wisp:body()). unauthorized_response(Realm) -> Realm@1 = <<<<"Basic realm=\""/utf8, Realm/binary>>/binary, "\""/utf8>>, _pipe = 401, _pipe@1 = wisp:response(_pipe), _pipe@2 = wisp:string_body(_pipe@1, <<"Unauthorized"/utf8>>), fun gleam@http@response:set_header/3( _pipe@2, <<"WWW-Authenticate"/utf8>>, Realm@1 ). -file("src/wisp_basic_auth.gleam", 72). -spec forbidden_response() -> gleam@http@response:response(wisp:body()). forbidden_response() -> _pipe = 403, _pipe@1 = wisp:response(_pipe), wisp:string_body(_pipe@1, <<"Forbidden"/utf8>>). -file("src/wisp_basic_auth.gleam", 26). ?DOC( " Middleware that validates an `Authorization: Basic` header\n" " against a known list of client ids and passwords within a realm.\n" " \n" " The basic authentication scheme is based on the model that the \n" " user agent must authenticate itself with a user-ID and a password \n" " for each realm.\n" " \n" " The realm value should be considered an opaque string which can \n" " only be compared for equality with other realms on that server.\n" " \n" " Example header: `Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==`\n" " \n" " ```gleam\n" " use request <- validate_basic_auth(\"Agrabah\", [#(\"Aladdin\", \"open sesame\")])\n" " ```\n" ). -spec validate_basic_auth( gleam@http@request:request(wisp@internal:connection()), binary(), list({binary(), binary()}), fun((gleam@http@request:request(wisp@internal:connection())) -> gleam@http@response:response(wisp:body())) ) -> gleam@http@response:response(wisp:body()). validate_basic_auth(Request, Realm, Known_clients, Handler) -> case gleam@http@request:get_header(Request, <<"Authorization"/utf8>>) of {error, _} -> unauthorized_response(Realm); {ok, Auth_header} -> case check_authorization(Auth_header, Known_clients) of {ok, _} -> Handler(Request); {error, nil} -> forbidden_response() end end.