-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from RamonPage/v0.3.0
v0.3.0
- Loading branch information
Showing
12 changed files
with
450 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
defmodule ExAzureKeyVault.ClientAssertionAuth do | ||
@moduledoc """ | ||
Internal module for getting authentication token for Azure connection using client assertion. | ||
""" | ||
alias __MODULE__ | ||
alias ExAzureKeyVault.HTTPUtils | ||
|
||
@enforce_keys [:client_id, :tenant_id, :cert_base64_thumbprint, :cert_private_key_pem] | ||
defstruct( | ||
client_id: nil, | ||
tenant_id: nil, | ||
cert_base64_thumbprint: nil, | ||
cert_private_key_pem: nil | ||
) | ||
|
||
@type t :: %__MODULE__{ | ||
client_id: String.t, | ||
tenant_id: String.t, | ||
cert_base64_thumbprint: String.t, | ||
cert_private_key_pem: String.t | ||
} | ||
|
||
@doc ~S""" | ||
Creates `%ExAzureKeyVault.ClientAssertionAuth{}` struct with account tokens and cert data. | ||
## Examples | ||
iex(1)> ExAzureKeyVault.ClientAssertionAuth.new("6f185f82-9909...", "6f1861e4-9909...", "Dss7v2YI3GgCGfl...", "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEF...") | ||
%ExAzureKeyVault.ClientAssertionAuth{ | ||
client_id: "6f185f82-9909...", | ||
tenant_id: "6f1861e4-9909...", | ||
cert_base64_thumbprint: "Dss7v2YI3GgCGfl...", | ||
cert_private_key_pem: "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEF..." | ||
} | ||
""" | ||
@spec new(String.t, String.t, String.t, String.t) :: ClientAssertionAuth.t | ||
def new(client_id, tenant_id, cert_base64_thumbprint, cert_private_key_pem) do | ||
%ClientAssertionAuth{ | ||
client_id: client_id, | ||
tenant_id: tenant_id, | ||
cert_base64_thumbprint: cert_base64_thumbprint, | ||
cert_private_key_pem: cert_private_key_pem | ||
} | ||
end | ||
|
||
@doc ~S""" | ||
Returns bearer token for Azure connection using client assertion. | ||
## Examples | ||
iex(1)> ExAzureKeyVault.ClientAssertionAuth.new("6f185f82-9909...", "6f1861e4-9909...", "Dss7v2YI3GgCGfl...", "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEF...") | ||
...(1)> |> ExAzureKeyVault.ClientAssertionAuth.get_bearer_token() | ||
{:ok, "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."} | ||
""" | ||
@spec get_bearer_token(ClientAssertionAuth.t) :: {:ok, String.t} | {:error, any} | ||
def get_bearer_token(%ClientAssertionAuth{} = params) do | ||
client_assertion = auth_client_assertion( | ||
params.client_id, | ||
params.tenant_id, | ||
params.cert_base64_thumbprint, | ||
params.cert_private_key_pem | ||
) | ||
url = auth_url(params.tenant_id) | ||
body = auth_body(params.client_id, client_assertion) | ||
headers = HTTPUtils.headers_form_urlencoded | ||
options = HTTPUtils.options_ssl | ||
case HTTPoison.post(url, body, headers, options) do | ||
{:ok, %HTTPoison.Response{status_code: 200, body: body}} -> | ||
response = Poison.decode!(body) | ||
{:ok, "Bearer #{response["access_token"]}"} | ||
{:ok, %HTTPoison.Response{status_code: status, body: ""}} -> | ||
HTTPUtils.response_client_error_or_ok(status, url) | ||
{:ok, %HTTPoison.Response{status_code: status, body: body}} -> | ||
HTTPUtils.response_client_error_or_ok(status, url, body) | ||
{:error, %HTTPoison.Error{reason: :nxdomain}} -> | ||
HTTPUtils.response_server_error(:nxdomain, url) | ||
{:error, %HTTPoison.Error{reason: reason}} -> | ||
HTTPUtils.response_server_error(reason) | ||
_ -> | ||
{:error, "Something went wrong"} | ||
end | ||
end | ||
|
||
@spec auth_url(String.t) :: String.t | ||
defp auth_url(tenant_id) do | ||
"https://login.microsoftonline.com/#{tenant_id}/oauth2/v2.0/token" | ||
end | ||
|
||
@spec auth_body(String.t, String.t) :: tuple | ||
defp auth_body(client_id, client_assertion) do | ||
{:form, [ | ||
grant_type: "client_credentials", | ||
client_id: client_id, | ||
client_assertion: client_assertion, | ||
client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer", | ||
scope: "https://vault.azure.net/.default" | ||
]} | ||
end | ||
|
||
@spec auth_client_assertion(String.t, String.t, String.t, String.t) :: String.t | ||
defp auth_client_assertion(client_id, tenant_id, cert_base64_thumbprint, cert_private_key_pem) do | ||
signer = Joken.Signer.create("RS256", %{"pem" => cert_private_key_pem}, %{"x5t" => cert_base64_thumbprint}) | ||
sub = client_id | ||
iss = client_id | ||
jti = Joken.generate_jti() | ||
nbf = Joken.current_time() | ||
exp = Joken.current_time() + 60 # in 1 minute | ||
aud = "https://login.microsoftonline.com/#{tenant_id}/oauth2/v2.0/token" | ||
{:ok, claims} = Joken.generate_claims(%{}, %{sub: sub, iss: iss, jti: jti, nbf: nbf, exp: exp, aud: aud}) | ||
{:ok, jwt, _} = Joken.encode_and_sign(claims, signer) | ||
jwt | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.