\section{Looking up IDPs through SeamlessAccess.org}\label{SeamlessAccessAPI}% ===> this file was generated automatically by noweave --- better not edit it

Here we provide the module {\Tt{}weblogin.seamlessaccess\nwendquote}.

There is a global service, SeamlessAccess.org, that provides SSO login services 
for academic institutions.
Essentially, what it does is to provide a look-up service for academic identity 
providers.
We will provide two functions using SeamlessAccess.org:
\begin{enumerate}
\item Search for an institution by name.
\item Look up an institution by unique ID.
\end{enumerate}

The module is structured as follows.
\nwfilename{seamlessaccess.nw}\nwbegincode{1}\sublabel{NW1Eki1K-1ZFmcj-1}\nwmargintag{{\nwtagstyle{}\subpageref{NW1Eki1K-1ZFmcj-1}}}\moddef{\code{}seamlessaccess.py\edoc{}~{\nwtagstyle{}\subpageref{NW1Eki1K-1ZFmcj-1}}}\endmoddef\nwstartdeflinemarkup\nwenddeflinemarkup
import requests

\LA{}functions~{\nwtagstyle{}\subpageref{NW1Eki1K-nRuDO-1}}\RA{}
\nwnotused{[[seamlessaccess.py]]}\nwendcode{}\nwbegindocs{2}We will test these functions using the following test script.
\nwenddocs{}\nwbegincode{3}\sublabel{NW1Eki1K-wwHSm-1}\nwmargintag{{\nwtagstyle{}\subpageref{NW1Eki1K-wwHSm-1}}}\moddef{test \code{}seamlessaccess.py\edoc{}~{\nwtagstyle{}\subpageref{NW1Eki1K-wwHSm-1}}}\endmoddef\nwstartdeflinemarkup\nwenddeflinemarkup
from weblogin.seamlessaccess import *

\LA{}test functions~{\nwtagstyle{}\subpageref{NW1Eki1K-1hnhZk-1}}\RA{}
\nwnotused{test [[seamlessaccess.py]]}\nwendcode{}\nwbegindocs{4}\nwdocspar

\subsection{Look up an institution by unique ID}\label{LookUpByID}

We can look up an institution by unique ID (what appears to be a SHA1 hash).
This is simply a GET request resulting in a JSON-formatted response.
\nwenddocs{}\nwbegincode{5}\sublabel{NW1Eki1K-nRuDO-1}\nwmargintag{{\nwtagstyle{}\subpageref{NW1Eki1K-nRuDO-1}}}\moddef{functions~{\nwtagstyle{}\subpageref{NW1Eki1K-nRuDO-1}}}\endmoddef\nwstartdeflinemarkup\nwusesondefline{\\{NW1Eki1K-1ZFmcj-1}}\nwprevnextdefs{\relax}{NW1Eki1K-nRuDO-2}\nwenddeflinemarkup
def get_entity_data_by_id(id):
  """
  Requests entity data from SeamlessAccess.org for entity with unique ID `id`.
  Returns JSON (dictionary) containing data.
  """
  response = requests.get(f"https://md.seamlessaccess.org/entities/\{id\}.json")
  try:
    return response.json()
  except:
    raise Exception(f"invalid response from SeamlessAccess.org for ID \{id\}")
\nwalsodefined{\\{NW1Eki1K-nRuDO-2}}\nwused{\\{NW1Eki1K-1ZFmcj-1}}\nwendcode{}\nwbegindocs{6}\nwdocspar

We can test this functions as follows:
\nwenddocs{}\nwbegincode{7}\sublabel{NW1Eki1K-1hnhZk-1}\nwmargintag{{\nwtagstyle{}\subpageref{NW1Eki1K-1hnhZk-1}}}\moddef{test functions~{\nwtagstyle{}\subpageref{NW1Eki1K-1hnhZk-1}}}\endmoddef\nwstartdeflinemarkup\nwusesondefline{\\{NW1Eki1K-wwHSm-1}}\nwprevnextdefs{\relax}{NW1Eki1K-1hnhZk-2}\nwenddeflinemarkup
def test_get_entity_data_by_id():
  data = get_entity_data_by_id("\{sha1\}e26e5d098f073536d0351577c98c83825f0f922c")
  assert data["id"] == "\{sha1\}e26e5d098f073536d0351577c98c83825f0f922c"
\nwalsodefined{\\{NW1Eki1K-1hnhZk-2}}\nwused{\\{NW1Eki1K-wwHSm-1}}\nwendcode{}\nwbegindocs{8}\nwdocspar

The resulting JSON data for this particular ID is:
\begin{pycode}
import json
from weblogin.seamlessaccess import *

print(r"\begin{minted}{json}")
print(json.dumps(
  get_entity_data_by_id("{sha1}e26e5d098f073536d0351577c98c83825f0f922c"),
  indent=2
))
print(r"\end{minted}")
\end{pycode}

\subsection{Searching for an institution by name}

We can also search for an institution by name.
This yields a list of JSON objects as in \cref{LookUpByID}.
\nwenddocs{}\nwbegincode{9}\sublabel{NW1Eki1K-nRuDO-2}\nwmargintag{{\nwtagstyle{}\subpageref{NW1Eki1K-nRuDO-2}}}\moddef{functions~{\nwtagstyle{}\subpageref{NW1Eki1K-nRuDO-1}}}\plusendmoddef\nwstartdeflinemarkup\nwusesondefline{\\{NW1Eki1K-1ZFmcj-1}}\nwprevnextdefs{NW1Eki1K-nRuDO-1}{\relax}\nwenddeflinemarkup
def find_entity_data_by_name(name):
  """
  Searches SeamlessAccess.org for an institution by name `name`.
  Returns a list of institutions' data.
  """
  response = requests.get(f"https://md.seamlessaccess.org/entities/?q=\{name\}")
  try:
    return response.json()
  except:
    raise Exception(f"invalid response from SeamlessAccess.org for name \{name\}")
\nwused{\\{NW1Eki1K-1ZFmcj-1}}\nwendcode{}\nwbegindocs{10}\nwdocspar

We can test this functions as follows:
\nwenddocs{}\nwbegincode{11}\sublabel{NW1Eki1K-1hnhZk-2}\nwmargintag{{\nwtagstyle{}\subpageref{NW1Eki1K-1hnhZk-2}}}\moddef{test functions~{\nwtagstyle{}\subpageref{NW1Eki1K-1hnhZk-1}}}\plusendmoddef\nwstartdeflinemarkup\nwusesondefline{\\{NW1Eki1K-wwHSm-1}}\nwprevnextdefs{NW1Eki1K-1hnhZk-1}{\relax}\nwenddeflinemarkup
def test_find_entity_data_by_name():
  data = find_entity_data_by_name("KTH")
  assert data[0]["id"] == "\{sha1\}e26e5d098f073536d0351577c98c83825f0f922c"
\nwused{\\{NW1Eki1K-wwHSm-1}}\nwendcode{}

\nwixlogsorted{c}{{\code{}seamlessaccess.py\edoc{}}{NW1Eki1K-1ZFmcj-1}{\nwixd{NW1Eki1K-1ZFmcj-1}}}%
\nwixlogsorted{c}{{functions}{NW1Eki1K-nRuDO-1}{\nwixu{NW1Eki1K-1ZFmcj-1}\nwixd{NW1Eki1K-nRuDO-1}\nwixd{NW1Eki1K-nRuDO-2}}}%
\nwixlogsorted{c}{{test \code{}seamlessaccess.py\edoc{}}{NW1Eki1K-wwHSm-1}{\nwixd{NW1Eki1K-wwHSm-1}}}%
\nwixlogsorted{c}{{test functions}{NW1Eki1K-1hnhZk-1}{\nwixu{NW1Eki1K-wwHSm-1}\nwixd{NW1Eki1K-1hnhZk-1}\nwixd{NW1Eki1K-1hnhZk-2}}}%
\nwbegindocs{12}\nwdocspar

The resulting JSON data for this particular ID is the following.
Note that the difference compared to the data in \cref{LookUpByID} is that this 
is one element in a list.
\begin{pycode}
import json
from weblogin.seamlessaccess import *

print(r"\begin{minted}{json}")
print(json.dumps(
  find_entity_data_by_name("KTH"),
  indent=2
))
print(r"\end{minted}")
\end{pycode}
\nwenddocs{}
