Ethereum User Authentication

Penny Li
3 min readFeb 21, 2024

In decentralized applications, unlike traditional web applications that rely on centralized databases and authentication, has its own challenges and opportunities. To this end, smart contract-based authentication serves as the backbone of managing user registration and login using Ethereum addresses as unique identifiers.

YouTube Tutorial

The video that goes through the below content in streaming format is as follows:

Below is the code for a basic authentication contract:

https://gist.github.com/LuckyPen3584/adbf9d4316476265afa1f8938508e13d

In the above code:

pragma solidity ^0.8.0; specifies the Solidity compiler version to use, ensuring compatibility

contract BasicAuth begins the declaration of a new contract called ‘BasicAuth’

struct User {string username; bool exists;} represents a user within a smart contract containing two fields:

username of the string data type that holds the username of the users

exists of the boolean data type that indicates whether a user has been registered in the contract

mapping(address => User) private users; declares a mapping named users, which is a key-value store for associating Ethereum addresses with User structs.

event UserRegistered(address userAddress, string username); emits an event containing the address and username of the user when a new user is registered in the system.

event UserLoggedIn(address userAddress); emits the ‘UserLoggedIn’ event, including the user’s address as an argument, when a user logs into the system.

function register(string calldata _username) external {

require(!users[msg.sender].exists, “User already exists”);

users[msg.sender] = User({

username: _username,

exists: true

});

emit UserRegistered(msg.sender, _username); } onboards a new user to the contract, associating a unique Ethereum address (‘msg.sender’) with a ‘username’.

require(!users[msg.sender].exists, “User already exists”); checks if a user already exists as a registered user.

users[msg.sender] = User({username: _username, exists: true}); creates a new ‘User’ struct if the user does not already exist and assigns to the caller’s address in the ‘users’ mapping.

function login() external {

require(users[msg.sender].exists, “User does not exist”);

emit UserLoggedIn(msg.sender); } declares a function named ‘login’ with ‘external’ visibility, so it can only be called from outside the contract.

‘require(users[msg.sender].exists, “User does not exist”);’ checks if the caller of the function ‘msg.sender’ is registered as a user in the contract

If the check passes indicating the user does exist, ‘emit UserLoggedIn(msg.sender);’ emits the ‘UserLoggedIn’ event with ‘msg.sender’ as its parameter.

function getUsername() external view returns (string memory) {

require(users[msg.sender].exists, “User does not exist”);

return users[msg.sender].username; } retrieves the username associated with the Ethereum address of the caller (‘msg.sender’).

‘require(users[msg.sender].exists, “User does not exist”);’ checks is the user exists in the contract.

If the check passes indicating the user does exist, return users[msg.sender].username; returns the ‘username’ associated with the caller’s address.

Please visit my substack page for more articles like this one.

Medium’s Boost / Hyper-Speed AI / FREE GPTs alternative / AI Art

--

--