PlugHmac

Auth Plug

Installation

The package can be installed by adding plug_hmac to your list of dependencies in mix.exs:

def deps do
[
{:plug_hmac, "~> 0.4"}
]
end

Usage

Configuration

Add body_reader to your Phoenix's Endpoint

plug Plug.Parsers,
parsers: [:urlencoded, :multipart, :json],
pass: ["*/*"],
body_reader: {PlugHmac.CacheBodyReader, :read_body, []},
json_decoder: Phoenix.json_library()

For Backend

plug PlugHmac,
error_handler: __MODULE__,
secret_handler: __MODULE__,
hmac_algo: :sha256,
client_signature_name: "authorization"
@behaviour PlugHmac.ErrorHandler
@behaviour PlugHmac.SecretHandler
## callback for error_handler
def handle(conn, _error) do
# you can case error here
# or update conn here
# must return conn
conn
end
## callback for secret_handler
def get_secret(client_id) do
# get your secret key
{:ok, your_secret_key}
end

For Client

# make_header(
# hmac_algo,
# secret_handler,
# client_id,
# method,
# path,
# query_string,
# body,
# nonce \\ nil
# )
PlugHmac.make_header(:sha256, __MODULE__, "test_id", "GET", "/api/test_auth", "a1=123&a2=456", "body string")

Principle

客户端在请求时,需要在HTTPHeader增加Authorization:

Authorization: hmac id=test_id,signature=xpSI4lZe5c%2BxlNe%2BUK6MQU8RHZNTjL1CTgQLbFamoYU%3D,nonce=vrlaY%2BzdC2S7cdWEXLiN

PlugHmacplug 会校验 Authorization 值的有效性

参数说明

在开始之前先说明将要用到的参数:

参数名参数值说明
MethodGET请求方法(全大写)
Path/api/test_auth请求路径
QueryString"a1=123&a2=456"将请求参数用&=拼接起来
Body"body string"请求的body字符串
ClientIDtest_id由接口提供方提供
SecretKeyqhN8mkCzaxjC1jWD4fDW由接口提供方提供
Nonceasd123随机值字符串

1. Authorization值

在拼接之前先使用 URI-encode,分别对各个参数值进行encode,然后再将其拼接起来,如下:

"hmac " + "id=" + ClientID + ",signature=" + Signature + ",nonce=" + Nonce

2. Signature值

首先按如下顺序拼接各个参数值:

ConcatString = Method+Path+QueryString+Body+Nonce
GET/api/test_autha1=123&a2=456body stringasd123

采用HMAC_SHA256算法使用SecretKey加密ConcatString的值,然后在进行Base64-encode,得到Signature 值,求值公式如下:

hmac.new(SecretKey, ConcatString, hashlib.sha256).digest().encode('base64')
Nop1kEtdf04S8Rr5U409Jmsx8Ic6zeWx2/HJZnLDRuM=