Skip to main content


Documentation & User Guides | FotoWare

Native or Mobile Application Authorization

Native and Mobile Applications

This variant of the authorization process is for native applications (or native apps), such as mobile apps, desktop applications or plugins for native desktop applications, such as Microsoft Office. A native app is a public client, because it cannot securely store a secret, as the secret could be retrieved by reverse-engineering the code of the native application. This means that native apps cannot authenticate themselves to FotoWeb. Native apps use authorization code grant, which means that the client first receives an intermediate authorization code from the server, which is then used to request an access token for accessing the FotoWeb API. This two-step process requires the client to send a second request to the server, where the client has to prove possession of the authorization code using a mechanism called proof key for code exchange (PKCE). This prevents malicious applications running on the same device as the client application from intercepting authorization codes or access tokens by taking control of the redirection endpoint.

User Experience

  1. The user starts the native application
  2. The native application opens a browser window using the system's default browser (e.g., Chrome, Firefox, Microsoft Edge or Safari).
  3. If the user isn't already logged into FotoWeb browser, then the regular FotoWeb login page is shown. Otherwise, proceed to step 4.
  4. The user is asked to authorize the application to access the user's information. This is done in a user interface that is part of FotoWeb, which should display the name of the application, a logo and a list of permissions to be granted to the application.
  5. The user is redirected to the application and signed in. The application can now use the FotoWeb API to access information in FotoWeb and do actions on the user's behalf.

Application registration

When registering the application in the FotoWeb site settings (Settings tab, then Services > Applications), choose Native / mobile.
No client secret is generated.

Launching a browser window

Native interactive applications should open a separate browser application (the standard browser chosen by the user on the device) for the authorization process. This makes it easier for the user to trust a third-party application, since the application cannot tamper with the browser and any credentials or other sensitive information entered by the user. Also, a native browser allows the user to reliably check the connection state (e.g., whether HTTPS is used and the certificates are in order) and use a password manager. Examples:

  • If the application is a desktop application running on Windows or Mac OS, and the user has chosen Chrome as the default browser, then the application should launch Chrome.
  • If the application is a mobile application, then it should launch the default browser app on the device, such as Safari or Chrome.

Protocol Flow

The client opens a browser window to the following URL (line-breaks are added for readability. All parameter values must be URL-encoded):




response_type REQUIRED. Must always be code.
client_id REQUIRED. The unique ID of the client, which was obtained during client registration.

The redirection endpoint URI of the client.

If given, it MUST match with one of the redirection endpoint URIs registered for the client.

OPTIONAL if the application only has one registration endpoint.

REQUIRED if the application has more than one registration endpoint.


REQUIRED: This SHOULD be a unique, cryptographically safe random string.

code_challenge REQUIRED: Code challenge. See the block about PKCE below.
code_challenge_method REQUIRED: Code challenge method. Must be S256. See the block about PKCE below.

Public clients (e.g., native applications) are REQUIRED to use the PKCE parameters code_challenge and code_challenge_method. This prevents interception of the authorization code by malicious applications or websites listening on the redirection endpoint.

For more information on generating the value for code_challenge, please see the section "Proof Key for Code Exchange".

This request may result in the user being shown a login prompt for FotoWeb.

On success, the server responds by redirecting the user to the redirection endpoint URI of the client. This is always one of the redirection endpoint registered for the client and, if given, the redirection URI passed in the request as redirect_uri.

Parameters are added to the query part of the redirection URI as follows (line-breaks added for readability. All parameter values are URL-encoded):




code The authorization code which is used to request the access token in the next request

This is always identical to the string passed to the request in the state parameter.

The client SHOULD check that the returned string is identical to the sent string.

This is to protect against cross-site request forgery (CSRF).

The client then makes the following request to the token endpoint to obtain the access token (line-breaks are added for readability.

This request MUST NOT be sent by the user agent, as it would expose client credentials and access tokens to the user agent, resource owner and potentially others. For example, if the client is a web application, then this request SHOULD be sent by the back-end (server) of the application, rather than JavaScript code running in the browser (which would also fail due to cross-site request limitations (CORS)).

If the client is a web application without a back-end (pure AJAX application with a static web server), or sending the request from the back-end is not feasible, then it is recommended to use implicit grant type instead (see the next section).

All parameter values must be URL-encoded):

Content-Type: application/x-www-form-urlencoded
Accept: application/json





grant_type REQUIRED. Must always be string "authorization_code"
client_id REQUIRED. The unique ID of the client, which was obtained during client registration.
code REQUIRED. The authorization code which was returned by the authorization request.

The redirection endpoint URI of the client.

REQUIRED if the redirection_uri parameter was also given in the authorization request, and its value must be identical.

MUST NOT BE GIVEN if the redirection_uri parameter was not given in the authorization request.

code_verifier REQUIRED: Code verifier. See below.

The code_verifier parameter is REQUIRED if a code_challenge was sent in the prior authorization request, which is REQUIRED for public clients and OPTIONAL for confidential clients.

The parameter value MUST be equal to the code verifier string that was generated for computing the code challenge.

This ensures that only the application that sent the authorization request can use the authorization code to request an access token. A different (malicious) application would not know the code verifier and thus would be unable to request an access token.

On success, the server responds as follows:

200 OK
Content-Type: application/json

with the following response body:

  "access_token": ACCESS_TOKEN,
  "token_type": "bearer",
  "expires_in": EXPIRES_IN_SECONDS,
  "refresh_token": REFRESH_TOKEN




access_token The access token that is used to authorize requests to the FotoWeb API 
token_type This is always bearer.
expires_in Number of seconds after which the token is expected to expire.
refresh_token OPTIONAL: A refresh token that can be used to request a new access token. For more information, see the section "Refreshing Tokens".

The application can obtain the access token by parsing the response body.

Refresh tokens are highly sensitive, as they have long (or infinite) expiration times and can be used to request new access tokens.

A client SHOULD store the refresh token in a safe place so it cannot be accessed by unauthorized parties. A client SHOULD NOT expose a refresh token to a user agent (browser). A client that does not use refresh tokens SHOULD NOT store the refresh token at all.

Proof Key for Code Exchange (PKCE)

The OAuth 2.0 PKCE (Proof Key for Code Exchange) extension (RFC 7636) is used by applications to prove possession of the authorization code when redeeming the authorization code to request an access token. This prevents interception of the authorization code by malicious applications or websites listening on the redirection endpoint. PKCE is required for native applications and optional for web applications. PKCE is used by sending the following parameters in the authorization request:

The code_challenge_method parameter must always be "S256". Plain text PKCE is not supported by FotoWeb.

The code_challenge parameter must be as follows:

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

i.e., the SHA256 hash of a code_verifier string, encoded as URL-friendly Base64 (using the character '-' for '+' and '_' for '/'):

static string EncodeBase64URL(byte[] arg)
    string s = Convert.ToBase64String(arg); // Regular base64 encoder
    s = s.Split('=')[0]; // Remove any trailing '='s
    s = s.Replace('+', '-'); // 62nd char of encoding
    s = s.Replace('/', '_'); // 63rd char of encoding
    return s;

// Compute the code_challenge parameter from the code_verifyer
private static string MakeCodeChallenge(string codeVerifier)
    using (var sha256 = new SHA256CryptoServiceProvider())
        return EncodeBase64URL(sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(codeVerifier)));

The code_verifier string MUST be a random string of at least 43 and at most 128 characters. Each character MUST be one of the following:

  • An uppercase or lowercase character
  • A digit
  • The characters '-', '.', '_', '~'.

The code verifier SHOULD have enough entropy to make it impractical to guess the value. This can usually be achieved by using a cryptographically-safe random generator, such as

It is RECOMMENDED that the output of a suitable random number generator be used to create a 32-byte sequence. The octet sequence is then BASE64URL-encoded to produce a 43-byte URL safe string to use as the code verifier:

private static string MakeCodeVerifier(int numBytes = 32)
    using (var rng = new RNGCryptoServiceProvider())
        byte[] bytes = new byte[numBytes];
        return EncodeBase64URL(bytes);