Low-level API for generic web projects#

Web app that logs in users#

  1. Firstly, create an instance of the identity.web.Auth object, and assign it to a (typically global) variable:

    auth = identity.web.Auth(
        session=session,  # A session object is a key-value storage with a
                          # dict-like interface. Many web frameworks provide this.
        authority="https://login.microsoftonline.com/common",
        client_id="your_app_client_id",
        client_credential="your_secret",
        )
    
  2. Now, in your web app’s login controller, call the auth.log_in(scopes=["your_scope"], redirect_uri="https://your_app.example.com/redirect_uri") (see also log_in()) to obtain the auth_uri (and possibly a user_code), and then render them into your login html page.

  3. The second leg of log-in needs to be implemented in another controller, which calls auth.complete_log_in(incoming_query_parameters) (see also complete_log_in()). If its returned dict contains an error, then render the error to end user, otherwise your end user has successfully logged in, and his/her information is available as a dict returned by identity.web.Auth.get_user(). In particular, the returned dict contains a key named sub, whose value is the unique identifier which you can use to represent this end user in your app’s local database.

  4. Don’t forget to add one more controller for log out. You do it by calling auth.log_out("https://your_app.example.com"). Please refer to log_out()’s docs for more details about its return value.

All of the content above are demonstrated in this sample (link to be provided).

Web app that logs in users and calls a web API on their behalf#

Building on top of the previous scenario, you just need to call auth.get_token_for_user(["your_scope"]) to obtain a token object. See identity.web.Auth.get_token_for_user() for more details. And you can see it in action in this sample (link to be provided).

Generic API, currently used for Flask web apps#

class identity.web.Auth(*, session, client_id, oidc_authority=None, authority=None, client_credential=None, http_cache=None)#
__init__(*, session, client_id, oidc_authority=None, authority=None, client_credential=None, http_cache=None)#

Create an identity helper for a web app.

This instance is expected to be long-lived with the web app.

Parameters:
  • session (dict) – A dict-like object to hold the session data. If you are using Flask, you should pass in session. If you are using Django, you should pass in request.session.

  • oidc_authority (str) – The authority which your app registers with your OpenID Connect provider. For example, https://example.com/foo. This library will concatenate /.well-known/openid-configuration to form the metadata endpoint.

  • authority (str) – The authority which your app registers with your Microsoft Entra ID. For example, https://example.com/foo. Historically, the underlying library will sometimes automatically append “/v2.0” to it. If you do not want that behavior, you may use oidc_authority instead.

  • client_id (str) – The client_id of your web app, issued by its authority.

  • client_credential (str) – It is somtimes a string. The actual format is decided by the underlying auth library. TBD.

complete_log_in(auth_response=None)#

This is the second leg of the authentication/authorization.

It is used inside your redirect_uri controller.

Parameters:

auth_response (dict) –

A dict-like object containing the parameters issued by Identity Provider. If you are using Flask, you can pass in request.args. If you are using Django, you can pass in HttpRequest.GET.

If you were using Device Code Flow, you won’t have an auth response, in that case you can leave it with its default value None.

Returns:

  • On failure, a dict containing “error” and optional “error_description”, for you to somehow render it to end user.

  • On success, a dict as {“next_link”: “/path/to/next/page/if/any”} That dict is actually the claims from an already-validated ID token.

get_token_for_client(scopes)#

Get access token for the current app, with specified scopes.

Parameters:

scopes (list) – A list of scopes that your app will need to use.

Returns:

A dict representing the json response from identity provider.

  • A successful response would contain “access_token” key,

  • An error response would contain “error” and usually “error_description”.

See also OAuth2 specs.

get_token_for_user(scopes)#

Get access token silently for the current user, with specified scopes.

Parameters:

scopes (list) – A list of scopes that your app will need to use.

Returns:

A dict representing the json response from identity provider.

  • A successful response would contain “access_token” key,

  • An error response would contain “error” and usually “error_description”.

See also OAuth2 specs.

get_user()#

Returns None if the user has not logged in or no longer passes validation. Otherwise returns a dict representing the current logged-in user.

The dict will have following keys:

  • sub. It is the unique identifier of the current logged-in user. You can use it to create an entry in your web app’s local database.

  • Some of other claims

log_in(scopes=None, redirect_uri=None, state=None, prompt=None, next_link=None)#

This is the first leg of the authentication/authorization.

Parameters:
  • scopes (list) – A list of scopes that your app will need to use.

  • redirect_uri (str) –

    Optional. If present, it must be an absolute uri you registered for your web app. In Flask, if your redirect_uri function is named def auth_response(), then you can use url_for("auth_response", _external=True).

    If absent, your end users will log in to your web app using a different method named Device Code Flow. It is less convenient for end user, but still works.

  • state (str) – Optional. Useful when the caller wants keep their own state.

  • prompt (str) – Optional. Valid values are defined in OIDC

  • next_link (str) – The link, typically a path, to redirect to after login.

Returns a dict containing the auth_uri that you need to guide end user to visit. If your app has no redirect uri, this method will also return a user_code which you shall also display to end user for them to use during log-in.

log_out(homepage)#

Logs out the user from current app.

Parameters:

homepage (str) – The page to be redirected to, after the log-out. In Flask, you can pass in url_for("index", _external=True).

Returns:

An upstream log-out URL. You can optionally guide user to visit it, otherwise the user remains logged-in there, and can SSO back to your app.