write in progress...
This commit is contained in:
4
.formatter.exs
Normal file
4
.formatter.exs
Normal file
@@ -0,0 +1,4 @@
|
||||
# Used by "mix format"
|
||||
[
|
||||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||
]
|
||||
27
.gitignore
vendored
27
.gitignore
vendored
@@ -1,9 +1,24 @@
|
||||
/_build
|
||||
/cover
|
||||
/deps
|
||||
/doc
|
||||
# The directory Mix will write compiled artifacts to.
|
||||
/_build/
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover/
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps/
|
||||
|
||||
# Where third-party dependencies like ExDoc output generated docs.
|
||||
/doc/
|
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||
/.fetch
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
||||
*.beam
|
||||
/config/*.secret.exs
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
rfc5849-*.tar
|
||||
|
||||
|
||||
23
README.md
23
README.md
@@ -1,2 +1,21 @@
|
||||
# rfc5849
|
||||
OAuth/1 Elixir Implementation based on OTP
|
||||
# Rfc5849
|
||||
|
||||
**TODO: Add description**
|
||||
|
||||
## Installation
|
||||
|
||||
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
|
||||
by adding `rfc5849` to your list of dependencies in `mix.exs`:
|
||||
|
||||
```elixir
|
||||
def deps do
|
||||
[
|
||||
{:rfc5849, "~> 0.1.0"}
|
||||
]
|
||||
end
|
||||
```
|
||||
|
||||
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
|
||||
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
|
||||
be found at [https://hexdocs.pm/rfc5849](https://hexdocs.pm/rfc5849).
|
||||
|
||||
|
||||
30
config/config.exs
Normal file
30
config/config.exs
Normal file
@@ -0,0 +1,30 @@
|
||||
# This file is responsible for configuring your application
|
||||
# and its dependencies with the aid of the Mix.Config module.
|
||||
use Mix.Config
|
||||
|
||||
# This configuration is loaded before any dependency and is restricted
|
||||
# to this project. If another project depends on this project, this
|
||||
# file won't be loaded nor affect the parent project. For this reason,
|
||||
# if you want to provide default values for your application for
|
||||
# third-party users, it should be done in your "mix.exs" file.
|
||||
|
||||
# You can configure your application as:
|
||||
#
|
||||
# config :rfc5849, key: :value
|
||||
#
|
||||
# and access this configuration in your application as:
|
||||
#
|
||||
# Application.get_env(:rfc5849, :key)
|
||||
#
|
||||
# You can also configure a third-party app:
|
||||
#
|
||||
# config :logger, level: :info
|
||||
#
|
||||
|
||||
# It is also possible to import configuration files, relative to this
|
||||
# directory. For example, you can emulate configuration per environment
|
||||
# by uncommenting the line below and defining dev.exs, test.exs and such.
|
||||
# Configuration from the imported file will override the ones defined
|
||||
# here (which is why it is important to import them last).
|
||||
#
|
||||
# import_config "#{Mix.env()}.exs"
|
||||
71
lib/rfc5849.ex
Normal file
71
lib/rfc5849.ex
Normal file
@@ -0,0 +1,71 @@
|
||||
defmodule Rfc5849 do
|
||||
|
||||
@moduledoc """
|
||||
Documentation for Rfc5849.
|
||||
"""
|
||||
|
||||
defstruct [
|
||||
realm: nil,
|
||||
consumer_key: nil,
|
||||
consumer_secret: nil, # must be protected
|
||||
token: nil,
|
||||
token_secret: nil, # must be protected
|
||||
callback: nil,
|
||||
verifier: nil,
|
||||
signature: nil,
|
||||
signature_method: :hmac_sha1,
|
||||
timestamp: nil,
|
||||
nonce: nil,
|
||||
client: %{
|
||||
method: nil,
|
||||
headers: nil,
|
||||
params: nil
|
||||
}
|
||||
request: {}
|
||||
]
|
||||
|
||||
use GenServer
|
||||
|
||||
@doc """
|
||||
"""
|
||||
def init(args) do
|
||||
{:ok, args}
|
||||
end
|
||||
|
||||
@doc """
|
||||
"""
|
||||
def terminate(reason, state) do
|
||||
end
|
||||
|
||||
@doc """
|
||||
"""
|
||||
def handle_call(message, from, state) do
|
||||
end
|
||||
|
||||
@doc """
|
||||
"""
|
||||
def handle_cast({:set, {:client, param}}, state) do
|
||||
case param do
|
||||
{:method, method} -> :ok
|
||||
{:headers, headers} -> :ok
|
||||
{:params, params} -> :ok
|
||||
end
|
||||
end
|
||||
def handle_cast({:set, {:oauth, oauth}}, state) do
|
||||
case oauth do
|
||||
{:consumer_key, consumer_key} -> :ok
|
||||
{:consumer_secret, consumer_secret} -> :ok
|
||||
{:token, token} -> :ok
|
||||
{:token_secret, token_secret} -> :ok
|
||||
{:signature_method, signature_method} -> :ok
|
||||
end
|
||||
end
|
||||
def handle_cast(message, state) do
|
||||
end
|
||||
|
||||
@doc """
|
||||
"""
|
||||
def handle_info(message, state) do
|
||||
end
|
||||
|
||||
end
|
||||
18
lib/rfc5849.ex~
Normal file
18
lib/rfc5849.ex~
Normal file
@@ -0,0 +1,18 @@
|
||||
defmodule Rfc5849 do
|
||||
@moduledoc """
|
||||
Documentation for Rfc5849.
|
||||
"""
|
||||
|
||||
@doc """
|
||||
Hello world.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> Rfc5849.hello()
|
||||
:world
|
||||
|
||||
"""
|
||||
def hello do
|
||||
:world
|
||||
end
|
||||
end
|
||||
145
lib/rfc5849_lib.ex
Normal file
145
lib/rfc5849_lib.ex
Normal file
@@ -0,0 +1,145 @@
|
||||
defmodule Rfc5849.Lib do
|
||||
|
||||
@moduledoc """
|
||||
> request = %Rfc5849{}
|
||||
> Rfc5849.Lib.request(request)
|
||||
{:ok, method, target, header, params}
|
||||
"""
|
||||
|
||||
def encode_percent(str) do
|
||||
str |> URI.encode(&URI.char_unreserved?/1)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Add a nonce (24bytes) in Rfc5849 structure
|
||||
"""
|
||||
@spec nonce(Rfc5849.t()) :: Rfc5849.t()
|
||||
def nonce(struct) do
|
||||
nonce(struct, 24)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Add a nonce with a defined size in Rfc5849 structure
|
||||
"""
|
||||
@spec nonce(Rfc5849.t(), integer()) :: Rfc5849.t()
|
||||
def nonce(struct, size) do
|
||||
%Rfc5849{struct|nonce: gen_nonce(size)}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Generate a nonce with `:crypto.string_rand_bytes` function and
|
||||
encode it in base64. This code is based on OAuther.
|
||||
"""
|
||||
defp gen_nonce(size) do
|
||||
:crypto.strong_rand_bytes(size) |> Base.encode64()
|
||||
end
|
||||
|
||||
@doc """
|
||||
add a timestamp to Rfc5849 structure.
|
||||
"""
|
||||
@spec timestamp(Rfc5849.t()) :: Rfc5849.t()
|
||||
def timestamp(struct) do
|
||||
%Rfc5849{struct|timestamp: gen_timestamp()}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Generate a timestamp based on `:os.timestamp()` function. This code
|
||||
is based on OAuther
|
||||
"""
|
||||
defp gen_timestamp() do
|
||||
{megasec, sec, _microsec} = :os.timestamp()
|
||||
megasec * 1_000_000 + sec
|
||||
end
|
||||
|
||||
@doc """
|
||||
Generate a signature based on information present in the Rfc5849
|
||||
structure
|
||||
"""
|
||||
@spec sign(Rfc5849.t()) :: Rfc5849.t()
|
||||
def sign(%Rfc5849{signature_method: signature_method} = struct) do
|
||||
end
|
||||
|
||||
@doc """
|
||||
Generate a signature based on information in the Rfc5849 with a
|
||||
different method.
|
||||
"""
|
||||
@spec sign(Rfc5849.t(), atom()) :: Rfc5849.t()
|
||||
def sign(struct, method) do
|
||||
:ok
|
||||
end
|
||||
|
||||
@doc """
|
||||
Generate a plaintext signature and return it
|
||||
"""
|
||||
@spec gen_signature_plain(Rfc5849.t()) :: string()
|
||||
defp gen_signature_plain(struct) do
|
||||
:ok
|
||||
end
|
||||
|
||||
@doc """
|
||||
Generate hmac-sha1 signature and return it.
|
||||
"""
|
||||
@spec gen_signature_sha1(Rfc5849.t()) :: string()
|
||||
defp gen_signature_sha1(struct) do
|
||||
:ok
|
||||
end
|
||||
|
||||
@doc """
|
||||
Generate rsa-sha1 signature and return it.
|
||||
"""
|
||||
@spec gen_signature_rsa(Rfc5849.t()) :: string()
|
||||
defp gen_signature_rsa(struct) do
|
||||
:ok
|
||||
end
|
||||
|
||||
|
||||
@doc """
|
||||
Change the signature_method and regenerate the signature
|
||||
"""
|
||||
@spec signature_method(Rfc5849.t(), string()) :: Rfc5849.t()
|
||||
def signature_method(struct, method) do
|
||||
%Rfc5849{struct|signature_method: method} |> sign
|
||||
end
|
||||
|
||||
@doc """
|
||||
Set the callback and encode it correctly.
|
||||
"""
|
||||
@spec callback(Rfc5849.t(), string()) :: Rfc5849.t()
|
||||
def callback(struct, callback) do
|
||||
%Rfc5849{struct|callback: callback}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Set the verifier and encode it correctly.
|
||||
"""
|
||||
@spec verifier(Rfc5849.t(), string() | function()) :: Rfc5849.t()
|
||||
def verifier(struct, verifier) do
|
||||
%Rfc5849{struct|verifier: verifier}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Set the consumer_secret, this value can be a function returning
|
||||
{:ok, secret} or a string.
|
||||
"""
|
||||
@spec consumer_secret(Rfc5849.t(), string() | function()) :: Rfc5849.t()
|
||||
def consumer_secret(struct, secret) do
|
||||
end
|
||||
|
||||
@doc """
|
||||
Set the token_secret, this value can be a function returning
|
||||
{:ok, secret} or a string.
|
||||
"""
|
||||
@spec token_secret(Rfc5849.t(), string() | function()) :: Rfc5849.t()
|
||||
def token_secret(struct, secret) do
|
||||
end
|
||||
|
||||
@doc """
|
||||
Generate a base string based on the content of the structure
|
||||
"""
|
||||
def gen_base_string(struct) do
|
||||
method = struct.method
|
||||
host = struct.host
|
||||
path = struct.path
|
||||
query = struct.query
|
||||
end
|
||||
end
|
||||
2
lib/rfc5849_lib.ex~
Normal file
2
lib/rfc5849_lib.ex~
Normal file
@@ -0,0 +1,2 @@
|
||||
defmodule Rfc5869.Lib do
|
||||
end
|
||||
28
mix.exs
Normal file
28
mix.exs
Normal file
@@ -0,0 +1,28 @@
|
||||
defmodule Rfc5849.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :rfc5849,
|
||||
version: "0.1.0",
|
||||
elixir: "~> 1.8",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
deps: deps()
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help compile.app" to learn about applications.
|
||||
def application do
|
||||
[
|
||||
extra_applications: [:logger]
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help deps" to learn about dependencies.
|
||||
defp deps do
|
||||
[
|
||||
# {:dep_from_hexpm, "~> 0.3.0"},
|
||||
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
|
||||
]
|
||||
end
|
||||
end
|
||||
113
test/rfc5849_lib_test.exs
Normal file
113
test/rfc5849_lib_test.exs
Normal file
@@ -0,0 +1,113 @@
|
||||
defmodule Rfc5849.LibTest do
|
||||
|
||||
test "URI" do
|
||||
:ok
|
||||
end
|
||||
|
||||
test "do percent encoding" do
|
||||
original = "https://photos.example.net/initiate"
|
||||
result = "https%3A%2F%2Fphotos.example.net%2Finitiate"
|
||||
assert(Rfc5849.Lib.encode_percent(original) == result)
|
||||
end
|
||||
|
||||
test "generate signature base string" do
|
||||
struct = model_base_string()
|
||||
result = ["POST&http%3A%2F%2Fexample.com%2Frequest&a2%3Dr%2520b%26a3%3D2%2520q",
|
||||
"%26a3%3Da%26b5%3D%253D%25253D%26c%2540%3D%26c2%3D%26oauth_consumer_",
|
||||
"key%3D9djdj82h48djs9d2%26oauth_nonce%3D7d8f3e4a%26oauth_signature_m",
|
||||
"ethod%3DHMAC-SHA1%26oauth_timestamp%3D137131201%26oauth_token%3Dkkk",
|
||||
"9d7dh3k39sjv7"]
|
||||
assert(Rfc5849.Lib.base_string(struct) == result)
|
||||
end
|
||||
|
||||
test "set token secret" do
|
||||
struct = %Rfc5849{}
|
||||
Rfc5849.Lib.token_secret(struct)
|
||||
end
|
||||
|
||||
test "set consumer secret" do
|
||||
struct = %Rfc5849{}
|
||||
Rfc5849.Lib.consumer_secret(struct)
|
||||
end
|
||||
|
||||
test "generate nonce" do
|
||||
struct = %Rfc5849{}
|
||||
Rfc5849.Lib.nonce(struct)
|
||||
end
|
||||
|
||||
test "generate timestamp" do
|
||||
struct = %Rfc5849{}
|
||||
Rfc5849.Lib.timestamp(struct)
|
||||
end
|
||||
|
||||
test "generate plaintext signature" do
|
||||
struct = %Rfc5849{}
|
||||
Rfc5849.Lib.signature(struct, :plain)
|
||||
end
|
||||
|
||||
test "generate hmac-sha1 signature" do
|
||||
struct = %Rfc5849{}
|
||||
Rfc5849.Lib.signature(struct, :hmac_sha1)
|
||||
end
|
||||
|
||||
test "generate rsa-sha1 signature" do
|
||||
struct = %Rfc5849{}
|
||||
Rfc5849.Lib.signature(struct, :rsa_sha1)
|
||||
end
|
||||
|
||||
defp model1 do
|
||||
%Rfc5849{
|
||||
consumer_key: "dpf43f3p2l4k3l03",
|
||||
consumer_secret: "kd94hf93k423kf44",
|
||||
signature_method: "HMAC-SHA1",
|
||||
timestamp: "137131200",
|
||||
nonce: "wIjqoS",
|
||||
callback: "http%3A%2F%2Fprinter.example.com%2Fready",
|
||||
signature: "74KNZJeDHnMBp0EMJ9ZHt%2FXKycU%3D",
|
||||
realm: "Photos"
|
||||
}
|
||||
end
|
||||
|
||||
defp model2 do
|
||||
%Rfc5849{
|
||||
consumer_key: "dpf43f3p2l4k3l03",
|
||||
consumer_secret: "kd94hf93k423kf44",
|
||||
token: "hh5s93j4hdidpola",
|
||||
signature_method: "HMAC-SHA1",
|
||||
timestamp: "137131201",
|
||||
nonce: "walatlh",
|
||||
verifier: "hfdp7dh39dks9884",
|
||||
callback: "http%3A%2F%2Fprinter.example.com%2Fready",
|
||||
signature: "gKgrFCywp7rO0OXSjdot%2FIHF7IU%3D",
|
||||
realm: "Photos"
|
||||
}
|
||||
end
|
||||
|
||||
defp model3 do
|
||||
%Rfc5849{
|
||||
consumer_key: "dpf43f3p2l4k3l03",
|
||||
consumer_secret: "kd94hf93k423kf44",
|
||||
token: "nnch734d00sl2jdk",
|
||||
signature_method: "HMAC-SHA1",
|
||||
timestamp: "137131202",
|
||||
nonce: "chapoH",
|
||||
verifier: "hfdp7dh39dks9884",
|
||||
signature: "MdpQcU8iPSUjWoN%2FUDMsK2sui9I%3D",
|
||||
realm: "Photos"
|
||||
}
|
||||
end
|
||||
|
||||
def model_base_string do
|
||||
%Rfc5849{
|
||||
consumer_key: "9djdj82h48djs9d2",
|
||||
consumer_secret: "kd94hf93k423kf44",
|
||||
token: "kkk9d7dh3k39sjv7",
|
||||
signature_method: "HMAC-SHA1",
|
||||
timestamp: "137131201",
|
||||
nonce: "7d8f3e4a",
|
||||
signature: "MdpQcU8iPSUjWoN%2FUDMsK2sui9I%3D",
|
||||
realm: "bYT5CMsGcbgUdFHObYMEfcx6bsw%3D"
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
11
test/rfc5849_lib_test.exs~
Normal file
11
test/rfc5849_lib_test.exs~
Normal file
@@ -0,0 +1,11 @@
|
||||
defmodule Rfc5849.LibTest do
|
||||
|
||||
test "generate signature base string" do
|
||||
:ok
|
||||
end
|
||||
|
||||
test "generate signature" do
|
||||
:ok
|
||||
end
|
||||
|
||||
end
|
||||
8
test/rfc5849_test.exs
Normal file
8
test/rfc5849_test.exs
Normal file
@@ -0,0 +1,8 @@
|
||||
defmodule Rfc5849Test do
|
||||
use ExUnit.Case
|
||||
doctest Rfc5849
|
||||
|
||||
test "greets the world" do
|
||||
assert Rfc5849.hello() == :world
|
||||
end
|
||||
end
|
||||
8
test/rfc5849_test.exs~
Normal file
8
test/rfc5849_test.exs~
Normal file
@@ -0,0 +1,8 @@
|
||||
defmodule Rfc5849Test do
|
||||
use ExUnit.Case
|
||||
doctest Rfc5849
|
||||
|
||||
test "greets the world" do
|
||||
assert Rfc5849.hello() == :world
|
||||
end
|
||||
end
|
||||
1
test/test_helper.exs
Normal file
1
test/test_helper.exs
Normal file
@@ -0,0 +1 @@
|
||||
ExUnit.start()
|
||||
Reference in New Issue
Block a user