Skip to main content

Endpoint

POST /api/login

Authentication

None - This is a public endpoint.

Request Body

Username
string
required
The username of the account to authenticate.
ProvidedPassword
string
required
The plain text password for authentication.

Request Example

curl -X POST https://api.example.com/api/login \
  -H "Content-Type: application/json" \
  -d '{
    "Username": "johndoe",
    "ProvidedPassword": "SecurePassword123!"
  }'

Response

Success Response

Status Code: 200 OK Returns user details and a JWT access token.
loginResult
object
User information returned upon successful login.
accessToken
string
JWT access token for authenticating subsequent API requests. This token expires in 60 minutes.

Response Example

{
  "loginResult": {
    "userID": 12345,
    "userName": "johndoe",
    "firstName": "John",
    "lastName": "Doe",
    "email": "[email protected]",
    "phoneNumber": "+1234567890",
    "profileImage_MediaUrl": "https://example.com/images/profile.jpg"
  },
  "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Error Responses

Status Code: 404 Not Found Returned when the username does not exist in the system.
{
  "loginResult": null,
  "accessToken": ""
}
Status Code: 401 Unauthorized Returned when the password is incorrect.

Token Usage

Include the JWT access token in the Authorization header of subsequent API requests:
Authorization: Bearer {accessToken}
The token is valid for 60 minutes from the time of issuance.

JWT Token Structure

The access token contains the following claims:
  • sub: User ID (primary unique identifier)
  • unique_name: Username
  • email: Email address (empty string if not set)
  • phone_number: Phone number (empty string if not set)
  • exp: Token expiration timestamp
  • iss: Token issuer
  • aud: Token audience
The token is signed using HMAC SHA-256 algorithm.

Implementation Details

Source: /workspace/source/features/auth/auth.endpoints.cs:39-52
app.MapPost("/api/login", async (LoginRequest request, 
    SocialMediaDataContext context, 
    IPasswordHasher<string> passwordHasher, 
    ITokenProvider tokenProvider) =>
{
    var user = await context.Users
        .Where(u => u.UserName == request.Username)
        .Select(s => new { 
            s.UserID, s.UserName, s.LastName, s.PhoneNumber, 
            s.PasswordHash, s.Email, s.FirstName, s.ProfileImage_MediaUrl 
        })
        .FirstOrDefaultAsync();

    if (user is null) 
        return Results.NotFound(new AuthResponse { 
            loginResult = null, 
            accessToken = string.Empty 
        });
        
    var PasswordResult = passwordHasher.VerifyHashedPassword(
        string.Empty, 
        user.PasswordHash, 
        request.ProvidedPassword ?? string.Empty
    );
    bool isValid = PasswordResult != PasswordVerificationResult.Failed;
    if (!isValid) return Results.Unauthorized();

    string token = tokenProvider.Create(
        user.UserID, 
        user.UserName, 
        user.Email, 
        user.PhoneNumber
    );
    LoginResult resultData = new LoginResult { 
        userID = user.UserID, 
        userName = user.UserName, 
        firstName = user.FirstName, 
        lastName = user.LastName, 
        email = user.Email ?? string.Empty, 
        phoneNumber = user.PhoneNumber ?? string.Empty, 
        profileImage_MediaUrl = user.ProfileImage_MediaUrl ?? string.Empty 
    };
    AuthResponse responseData = new AuthResponse { 
        loginResult = resultData, 
        accessToken = token 
    };
    return Results.Ok(responseData);
});
Token Provider: /workspace/source/features/auth/auth.tokenProvider.cs:14-41
public string Create(long userId, string username, string? email, string? phoneNumber)
{
    string secretKey = configuration["Jwt:Key"] ?? string.Empty;
    var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));
    var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
    
    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity
        ([
            new Claim(JwtRegisteredClaimNames.Sub, userId.ToString()),
            new Claim(JwtRegisteredClaimNames.UniqueName, username),
            new Claim(JwtRegisteredClaimNames.Email, email ?? string.Empty),
            new Claim(JwtRegisteredClaimNames.PhoneNumber, phoneNumber ?? string.Empty),
        ]),
        Expires = DateTime.UtcNow.AddMinutes(60),
        SigningCredentials = credentials,
        Issuer = configuration["Jwt:Issuer"],
        Audience = configuration["Jwt:Issuer"]
    };
    
    var handler = new JsonWebTokenHandler();
    string token = handler.CreateToken(tokenDescriptor);
    return token;
}

Build docs developers (and LLMs) love