2FA

API: Internal/Beta

UCloud supports 2FA for all users using a TOTP backend.

Rationale

UCloud, for the most part, relies on the user’s organization to enforce best practices. UCloud can be configured to require additional factors of authentication via WAYF. On top of this UCloud allows you to optionally add TOTP based two-factor authentication.

https://cloud.sdu.dk uses this by enforcing 2FA of all users authenticated via the password backend.

Table of Contents

1. Examples
Description
Creating 2FA credentials
2. Remote Procedure Calls
Name Description
answerChallenge Answers a challenge previously issued by createCredentials
createCredentials Creates initial 2FA credentials and bootstraps a challenge for those credentials
twoFactorStatus Retrieves the 2FA status of the currently authenticated user
3. Data Models
Name Description
AnswerChallengeRequest No description
Create2FACredentialsResponse No description
TwoFactorStatusResponse No description

Example: Creating 2FA credentials

Frequency of useCommon
Actors
  • An authenticated user (user)
Communication Flow: Kotlin
TwoFactorAuthDescriptions.twoFactorStatus.call(
    Unit,
    user
).orThrow()

/*
TwoFactorStatusResponse(
    connected = false, 
)
*/
TwoFactorAuthDescriptions.createCredentials.call(
    Unit,
    user
).orThrow()

/*
Create2FACredentialsResponse(
    challengeId = "CHALLENGE ID", 
    otpAuthUri = "OTP URI", 
    qrCodeB64Data = "QR CODE BASE64 ENCODED", 
    secret = "SECRET", 
)
*/
TwoFactorAuthDescriptions.answerChallenge.call(
    AnswerChallengeRequest(
        challengeId = "CHALLENGE ID", 
        verificationCode = 999999, 
    ),
    user
).orThrow()

/*
Unit
*/
TwoFactorAuthDescriptions.twoFactorStatus.call(
    Unit,
    user
).orThrow()

/*
TwoFactorStatusResponse(
    connected = true, 
)
*/
Communication Flow: TypeScript
// Authenticated as user
await callAPI(AuthTwofactorApi.twoFactorStatus(
    {
    }
);

/*
{
    "connected": false
}
*/
await callAPI(AuthTwofactorApi.createCredentials(
    {
    }
);

/*
{
    "otpAuthUri": "OTP URI",
    "qrCodeB64Data": "QR CODE BASE64 ENCODED",
    "secret": "SECRET",
    "challengeId": "CHALLENGE ID"
}
*/
await callAPI(AuthTwofactorApi.answerChallenge(
    {
        "challengeId": "CHALLENGE ID",
        "verificationCode": 999999
    }
);

/*
{
}
*/
await callAPI(AuthTwofactorApi.twoFactorStatus(
    {
    }
);

/*
{
    "connected": true
}
*/
Communication Flow: Curl
# ------------------------------------------------------------------------------------------------------
# $host is the UCloud instance to contact. Example: 'http://localhost:8080' or 'https://cloud.sdu.dk'
# $accessToken is a valid access-token issued by UCloud
# ------------------------------------------------------------------------------------------------------

# Authenticated as user
curl -XGET -H "Authorization: Bearer $accessToken" "$host/auth/2fa/status" 

# {
#     "connected": false
# }

curl -XPOST -H "Authorization: Bearer $accessToken" "$host/auth/2fa" 

# {
#     "otpAuthUri": "OTP URI",
#     "qrCodeB64Data": "QR CODE BASE64 ENCODED",
#     "secret": "SECRET",
#     "challengeId": "CHALLENGE ID"
# }

curl -XPOST -H "Authorization: Bearer $accessToken" -H "Content-Type: content-type: application/json; charset=utf-8" "$host/auth/2fa/challenge" -d '{
    "challengeId": "CHALLENGE ID",
    "verificationCode": 999999
}'


# {
# }

curl -XGET -H "Authorization: Bearer $accessToken" "$host/auth/2fa/status" 

# {
#     "connected": true
# }
Communication Flow: Visual

Remote Procedure Calls

answerChallenge

API: Internal/Beta Auth: Public

Answers a challenge previously issued by createCredentials

Request Response Error
AnswerChallengeRequest Unit CommonErrorMessage

createCredentials

API: Internal/Beta Auth: Users

Creates initial 2FA credentials and bootstraps a challenge for those credentials

Request Response Error
Unit Create2FACredentialsResponse CommonErrorMessage

twoFactorStatus

API: Internal/Beta Auth: Users

Retrieves the 2FA status of the currently authenticated user

Request Response Error
Unit TwoFactorStatusResponse CommonErrorMessage

Data Models

AnswerChallengeRequest

API: Internal/Beta

data class AnswerChallengeRequest(
    val challengeId: String,
    val verificationCode: Int,
)
Properties
challengeId: String
verificationCode: Int

Create2FACredentialsResponse

API: Internal/Beta

data class Create2FACredentialsResponse(
    val otpAuthUri: String,
    val qrCodeB64Data: String,
    val secret: String,
    val challengeId: String,
)
Properties
otpAuthUri: String
qrCodeB64Data: String
secret: String
challengeId: String

TwoFactorStatusResponse

API: Internal/Beta

data class TwoFactorStatusResponse(
    val connected: Boolean,
)
Properties
connected: Boolean