Skip to content

Commit

Permalink
Add tests for decode_saml_request
Browse files Browse the repository at this point in the history
  • Loading branch information
LauraBeatris committed Mar 24, 2024
1 parent 317f969 commit 9d0a7e1
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 6 deletions.
2 changes: 2 additions & 0 deletions lib/oidc.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
defmodule ShinAuth.OIDC do
@moduledoc """
OpenID Connect utilities.
Performs decoding and validation based on the spec: https://openid.net/specs/openid-connect-discovery-1_0.html
"""

import ShinAuth.OIDC.ProviderConfiguration.Client
Expand Down
10 changes: 8 additions & 2 deletions lib/saml.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,18 @@ defmodule ShinAuth.SAML do
{:ok, Request.t()}
| {:error, Request.Error.t()}

def decode_saml_request(""), do: {:error, "Empty SAML request"}
def decode_saml_request(""),
do:
{:error,
%Request.Error{
tag: :malformed_saml_request,
message: "Verify if the SAML request is structured correctly by the Service Provider."
}}

def decode_saml_request(saml_request) do
error = %Request.Error{
tag: :malformed_saml_request,
message: "Invalid SAML request"
message: "Verify if the SAML request is structured correctly by the Service Provider."
}

if valid_xml?(saml_request) do
Expand Down
6 changes: 3 additions & 3 deletions lib/saml/request/request.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ defmodule ShinAuth.SAML.Request do
{:assertion_consumer_service_url, "/samlp:AuthnRequest/@AssertionConsumerServiceURL",
&{:ok, Utils.maybe_to_string(&1)}, optional: false},
field:
{:issuer, "/samlp:AuthnRequest/saml:Issuer/text()",
&{:ok, Utils.maybe_to_string(&1) |> String.trim()}, optional: false},
{:issuer, "/samlp:AuthnRequest/saml:Issuer/text()", &{:ok, Utils.maybe_to_string(&1)},
optional: false},
field:
{:issue_instant, "/samlp:AuthnRequest/@IssueInstant", &{:ok, Utils.maybe_to_string(&1)},
optional: false}
Expand All @@ -37,5 +37,5 @@ defmodule ShinAuth.SAML.Request.Utils do

def maybe_to_string(""), do: nil
def maybe_to_string(nil), do: nil
def maybe_to_string(value), do: to_string(value)
def maybe_to_string(value), do: to_string(value) |> String.trim()
end
2 changes: 1 addition & 1 deletion test/oidc_test.exs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule ShinTest.OIDCTest do
defmodule ShinAuth.OIDCTest do
import Mox

use ExSpec, async: true
Expand Down
68 changes: 68 additions & 0 deletions test/saml/request_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
defmodule ShinAuth.SAML.RequestTest do
use ExSpec, async: true

alias ShinAuth.SAML
alias ShinAuth.SAML.Request

describe "with malformed saml request" do
context "with empty xml" do
it "returns error" do
{:error,
%Request.Error{
tag: :malformed_saml_request,
message: "Verify if the SAML request is structured correctly by the Service Provider."
}} = SAML.decode_saml_request("")
end
end

context "with malformed xml element" do
it "returns error" do
{:error,
%Request.Error{
tag: :malformed_saml_request,
message: "Verify if the SAML request is structured correctly by the Service Provider."
}} =
SAML.decode_saml_request("""
<Invalid
""")
end
end

context "when missing saml request required element" do
saml_request_mock = """
<?xml version="1.0"?>
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_123" Version="2.0" IssueInstant="2023-09-27T17:20:42.746Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Destination="https://accounts.google.com/o/saml2/idp?idpid=C03gu405z" AssertionConsumerServiceURL="https://auth.example.com/sso/saml/acs/123">
<samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" AllowCreate="true"/>
</samlp:AuthnRequest>
"""

{:error,
%DataSchema.Errors{
errors: [issuer: "Field was required but value supplied is considered empty"]
}} = SAML.decode_saml_request(saml_request_mock)
end
end

describe "with valid saml request" do
context "returns parsed request struct" do
saml_request_mock = """
<?xml version="1.0"?>
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_123" Version="2.0" IssueInstant="2023-09-27T17:20:42.746Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Destination="https://accounts.google.com/o/saml2/idp?idpid=C03gu405z" AssertionConsumerServiceURL="https://auth.example.com/sso/saml/acs/123">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
https://example.com/123
</saml:Issuer>
<samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" AllowCreate="true"/>
</samlp:AuthnRequest>
"""

{:ok,
%Request{
id: "_123",
version: "2.0",
issue_instant: "2023-09-27T17:20:42.746Z",
issuer: "https://example.com/123",
assertion_consumer_service_url: "https://auth.example.com/sso/saml/acs/123"
}} = SAML.decode_saml_request(saml_request_mock)
end
end
end

0 comments on commit 9d0a7e1

Please sign in to comment.