diff --git a/index.html b/index.html index 222309e..154c3f1 100644 --- a/index.html +++ b/index.html @@ -327,6 +327,15 @@
  • Logout
  • +
  • + OAuth2 Authorization Request +
  • +
  • + OAuth2 Callback +
  • +
  • + OAuth2 Mobile Redirect +
  • Initialize the Server
  • @@ -1302,12 +1311,304 @@

    Response

    Success +

    OAuth2 Authorization Request

    curl "https://abs.example.com/auth/openid?code_challenge=1234&code_challenge_method=S256&redirect_uri=audiobookshelf%3A%2F%2Foauth&client_id=Audiobookshelf-App&response_type=code"
    +
    +
    +

    Response header (depending on SSO provider)

    +
    +
    Location: https://auth.example.com/application/o/authorize/?client_id=G9DbJqJ&scope=openid%20profile%20email&response_type=code&redirect_uri=https%3A%2F%2Fabs.example.com%2Fauth%2Fopenid%2Fmobile-redirect&state=2000&code_challenge=C424242&code_challenge_method=S256
    +
    +

    This endpoint starts a standard OAuth2 flow with PKCE (required - S256; see RFC7636), to log the user in using SSO.

    + +

    For the code_challenge, you must randomly generate a minimum 32-byte string called verifier (PKCE challenge). +With the verifier, you can then generate the challenge. See the examples on the right side.

    + +
    +

    Code Challenge Pseudo-Code

    +
    +
    code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
    +
    +
    +

    Code Challenge plain Javascript Code (all used functions are available in NodeJS and Browsers)

    +
    +
    function base64URLEncode(arrayBuffer) {
    +  let base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)))
    +  return base64String.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '')
    +}
    +
    +async function sha256(plain) {
    +  const encoder = new TextEncoder()
    +  const data = encoder.encode(plain)
    +  return await window.crypto.subtle.digest('SHA-256', data)
    +}
    +
    +function generateRandomString() {
    +  var array = new Uint32Array(42)
    +  window.crypto.getRandomValues(array)
    +  return Array.from(array, (dec) => ('0' + dec.toString(16)).slice(-2)).join('') // return as hex
    +}
    +
    +const verifier = generateRandomString()
    +const challenge = base64URLEncode(await sha256(verifier))
    +
    +

    On a valid request, it will return a 302-redirect (usually with a Location: header), which will point to the ABS-configured OAuth2 Provider. +You would usually have to open this redirect-URL in a Browser to present to the user. +Note that inside the redirect URL, among other parameters, there is a state parameter; save it for below.

    + +

    Note that you will have to preserve the cookies you receive in this call for using it in /auth/openid/callback (check if you need to set a parameter for the HTTP library you are using for that).

    + +

    When the user has logged in (successfully) inside the Browser, the Browser will redirect to the URL redirect_uri which should be a URL your website or app can open (like a universal app link). The call to the redirect_uri will include state and code GET parameters. Check if the state parameter is the same as above and use the code for the call to /auth/openid/callback.

    + +
    +

    Redirect URL which is opened in the user's browser by the SSO Provider

    +
    +
    redirect_uri?code=42&state=2000
    +

    HTTP Request

    +

    GET http://abs.example.com/auth/openid

    +

    Query Parameters

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ParameterTypeDefaultDescription
    code_challengeStringRequiredPKCE code_challenge you generated from verifier
    code_challenge_methodStringS256Must be S256
    response_typeStringcodeOnly code is supported
    redirect_uriStringRequiredURL where to redirect after a successful login. Must be whitelisted in ABS
    client_idStringRequiredThe name of your app (currently not used, but might be required at some point)
    + +

    Other parameters are ignored.

    +

    Response

    + + + + + + + + + + + + + + + + + + + + + + +
    StatusMeaningDescription
    302REDIRECTSuccess, save the state-parameter and follow the redirect
    400Bad RequestYou submitted an invalid parameter
    500Internal Server ErrorError in the flow
    +

    OAuth2 Callback

    curl "https://abs.example.com/auth/openid/callback?state=2000&code=42&code_verifier=1234"
    +
    +
    +

    The above command returns a JSON structured like this:

    +
    +
    {
    +   "userDefaultLibraryId":"b2bab335-d9aa-4141-8394-fd98767504d7",
    +   "serverSettings":{
    +      "scannerFindCovers":false,
    +      "metadataFileFormat":"json",
    +      "backupSchedule":false,
    +      "authOpenIDJwksURL":"https://auth.example.com/application/o/audiobookshelf/jwks/",
    +      "authOpenIDAutoLaunch":true,
    +      "…"
    +   },
    +   "Source":"docker",
    +   "user":{
    +      "oldUserId":"usr_1234lasdnlk",
    +      "itemTagsSelected":[],
    +      "createdAt":1672769098296,
    +      "librariesAccessible":[  ],
    +      "mediaProgress":[],
    +      "oldUserId":"usr_1234lasdnlk",
    +      "permissions":{
    +         "accessExplicitContent":true,
    +         "delete":true,
    +         "download":true,
    +         "upload":true,
    +         "accessAllLibraries":true,
    +         "…"
    +      },
    +      "seriesHideFromContinueListening":[],
    +      "token":"eyJhbGciOiJIUzI1NiIsInASDLKAMSDklmad.ASLDKlkma.PNKNASDPNdnknsdfoP",
    +      "type":"admin",
    +      "username":"example"
    +   },
    +   "ereaderDevices":[]
    +}
    +
    +

    This API call finalizes the OAuth2 flow. The behavior of this call depends on whether a redirect_uri was provided in the /auth/openid request:

    + + + +

    It's important to note that the call to /auth/openid/callback is stateful. This means that the cookies set during the /auth/openid call must be sent along with this request.

    +

    Query Parameters

    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ParameterTypeDefaultDescription
    stateStringRequiredThe state string you received when redirect_uri was called
    codeStringRequiredThe code you received when redirect_uri was called
    code_verifierStringRequiredThis is the verifier you generated when providing the code_challenge in the first request
    + +

    Other parameters are ignored.

    +

    Response

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    StatusMeaningDescription
    200OKSuccess, user data in payload
    302FOUNDSuccess, redirect to /login (internal use)
    400Bad RequestYou have no session
    401UnauthorizedError from the SSO provider
    500Internal Server ErrorError in the flow
    + +

    Error details are provided in the response body and in ABS logs.

    +

    OAuth2 Mobile Redirect

    curl "https://abs.example.com/auth/openid/mobile-redirect"
    +
    +

    This is an internal endpoint, which should not be called directly by an application. It is intended purely for the redirection of SSO providers.

    + +

    When you provide a redirect_uri in /auth/openid, ABS performs an important operation: it saves your redirect_uri and instructs the SSO provider to use /auth/openid/mobile-redirect instead. This endpoint, in turn, redirects to your original redirect_uri.

    + +

    This mechanism allows ABS to provide a https callback URL, which is particularly useful for mobile apps.

    + +

    This call does not require a cookie or session. It matches the redirect_uri using the state parameter.

    +

    HTTP Request

    +

    GET http://abs.example.com/auth/openid/mobile-redirect

    +

    Query Parameters

    + + + + + + + + + + + + + + + + + + + + +
    ParameterTypeDefaultDescription
    codeStringRequiredOAuth2 state
    stateStringRequiredOAuth2 code
    + +

    Other parameters are ignored.

    +

    Response

    + + + + + + + + + + + + + + + + + + + + + + +
    StatusMeaningDescription
    302REDIRECTSuccess
    400Bad RequestNo state or no redirect_uri associated to state
    500Internal Server ErrorError in the flow

    Initialize the Server

    curl -X POST "https://abs.example.com/init" \
       -H "Content-Type: application/json" \
       -d '{"newRoot": {"username": "root", "password": "*****"}}'
     

    This endpoint initializes a server for use with a root user. This is required for new servers without a root user yet.

    -

    HTTP Request

    +

    HTTP Request

    POST http://abs.example.com/init

    Parameters

    @@ -1342,7 +1643,7 @@

    New Root User Parameters

    The password of the new root user, may be empty.
    -

    Response

    +

    Response

    @@ -1372,9 +1673,9 @@

    Check the Server's Status

    }

    This endpoint reports the server's initialization status.

    -

    HTTP Request

    +

    HTTP Request

    GET http://abs.example.com/status

    -

    Response

    +

    Response

    Status
    @@ -1429,9 +1730,9 @@

    Ping the Server

    }
     

    This endpoint is a simple check to see if the server is operating and responding with JSON correctly.

    -

    HTTP Request

    +

    HTTP Request

    GET http://abs.example.com/ping

    -

    Response

    +

    Response

    Status
    @@ -1464,9 +1765,9 @@

    Response Schema

    Healthcheck

    curl "https://abs.example.com/healthcheck"
     

    This endpoint is a simple check to see if the server is operating and can respond.

    -

    HTTP Request

    +

    HTTP Request

    GET http://abs.example.com/healthcheck

    -

    Response

    +

    Response

    Status
    Status