Broadleaf Microservices
  • v1.0.0-latest-prod

Embedded Login with One-Time Passcode

Overview

Embedded Login allows authentication without cookies. A native application can provide a username/password form and authenticate via API. This is different from Universal Login, where the user is sent to the Auth service to login and then returns to the app. With Embedded Login, the user stays in the app the whole time.

Embedded Login is inherently less secure than Universal Login.

With a native login flow, an unauthorized party could decompile or intercept traffic to/from your application to get the Client ID and authentication URL. With this information the unauthorized party could create a rogue application, upload it to an application store, and use it to phish for usernames, passwords, and Access Tokens.

Configuration

Since it is less secure, embedded login is disabled by default. To use embedded login, set the property broadleaf.auth.login.embedded.enabled to true and enable "Embedded Login and Registration" in the admin on each Application Server where it is needed.

Note

PKCE is not supported when using embedded login.

(since 2.0.0) On the AuthorizedClient(s) you plan to use with embedded login, ensure you set AuthorizedClient.proofKeyRequired to false. To achieve this in the Broadleaf admin UI, you can go to Security > Authorization Servers > [your server] > Authorized Clients > [your embedded login client] > Advanced, and then update the 'Is Proof Key Required?' setting.

Register

Embedded user registration uses the /register/embedded/submit endpoint. Include the appropriate parameters and the new user object will be returned.

Request
curl --location --request POST 'https://localhost:8443/register/embedded/submit?client_id=heatclinic' \
--header 'Content-Type: application/json' \
--data-raw '{
"username": "test@test.com",
"password": "Pass1word!",
"email": "test@test.com",
"fullName": "Test test"
}'
Response
{
    "id": "01FK1M1ECD1VA60KQP2N580HHW",
    "fullName": "Test test",
    "username": "test@test.com",
    "email": "test@test.com",
    "serviceId": "01FK1M1DZNVSSN16YM9XJ10JTP",
    "type": "CUSTOMER",
    ...
}

Login

Embedded Login uses the /embedded/login endpoint. Send the client_id, username, and password to get back a one-time passcode. Use this passcode with the /oauth/token endpoint to get an access token that can be used for REST calls.

Request
curl --location --request POST 'https://localhost:8443/embedded/login?client_id=heatclinic&username=test@test.com&password=Pass1word!'
Response
{"token":"000zva0JVUnkaW0P1nQ0zny5GCjKYRlO"}

Access Token

Getting an access token with Embedded Login uses the same token endpoint as Universal Login. Include additional parameters for username and code purpose. Send the one-time passcode received from the /embedded/login endpoint as the code parameter. This will return an access token that can be used to authenticate REST calls to the various services. Include the scope OFFLINE_ACCESS to get a refresh token.

Request
curl --location --request POST 'https://localhost:8443/oauth/token?client_id=heatclinic&grant_type=authorization_code&username=test@test.com&purpose=OTP&scope=USER CUSTOMER_USER OFFLINE_ACCESS&code=000zva0JVUnkaW0P1nQ0zny5GCjKYRlO'
Response
{
    "access_token": "eyJ...iQ",
    "token_type": "bearer",
    "refresh_token": "eyJ...Tg",
    "expires_in": 299,
    "scope": "USER CUSTOMER_USER OFFLINE_ACCESS",
    "iss": "broadleaf-authentication",
    "max": 1635583859,
    "email_address": "test@test.com",
    ...
}

Using Access Tokens

Using access tokens with Embedded Login is the exact same as with Universal login. Use the access token as a bearer token header in the service request.

Here is an example request & response to the customer endpoint

Request
curl --location --request GET 'https://heatclinic.localhost:8456/api/customer/customers/01FK1M1DZNVSSN16YM9XJ10JTP' \
--header 'X-Application-Token: HEAT_CLINIC' \
--header 'Authorization: Bearer eyJ...iQ'
Response
{
    "id": "01FK1M1DZNVSSN16YM9XJ10JTP",
    "fullName": "Test test",
    "username": "test@test.com",
    "email": "test@test.com",
    ...
}

Using Refresh Tokens

Using refresh tokens with Embedded Login is the exact same as with Universal login. For in-depth info, see Refresh Token Grant Type.

To summarize, use the refresh_token grant type and include the refresh token received with the access token earlier to get back another access token & refresh token.

Request
curl --location --request POST 'https://localhost:8443/oauth/token?client_id=heatclinic&grant_type=refresh_token&scope=USER CUSTOMER_USER OFFLINE_ACCESS&refresh_token=eyJ...Tg'
Response
{
    "access_token": "eyJ...Ew",
    "token_type": "bearer",
    "refresh_token": "eyJ...2w",
    "expires_in": 299,
    "scope": "CUSTOMER_USER USER",
    "iss": "broadleaf-authentication",
    "max": 1635584444,
    "email_address": "test@test.com",
    ...
}

Logout

Logging out an embedded user uses the normal /login endpoint with the addition of the code parameter. Include the current refresh token as the code parameter and the token will be revoked. Since Embedded Login does not use cookies, neglecting the code parameter on logout would return success without actually changing anything.

Request
curl --location --request GET 'https://localhost:8443/logout?client_id=heatclinic&token=eyJ...2w'
Response
302 Found