Authentication Flow
Purpose and Scope
This document details the two-phase authentication mechanism used to establish a session with the JIIT Webportal API. It covers captcha acquisition, credential validation, token generation, and session initialization.
For information about managing active sessions and making authenticated API calls, see Session Management. For details on the encryption used during authentication, see Encryption System.
Overview
The JIIT Webportal API employs a two-phase authentication process that requires:
- Phase 1 (Pretoken Check): Username and captcha validation via
/token/pretoken-check - Phase 2 (Token Generation): Password validation and session token creation via
/token/generate-token1
Both phases require encrypted payloads and the LocalName header. The process is implemented in the Webportal.student_login() method.
Sources: pyjiit/wrapper.py111-143
Captcha Acquisition
Before authentication can begin, a valid captcha must be obtained from the API.
Captcha Structure
The Captcha class encapsulates three fields:
| Field | Type | Description |
|---|---|---|
captcha |
str |
The captcha answer string |
hidden |
str |
Base64-encoded captcha identifier |
image |
str |
Base64-encoded PNG image of the captcha |
Obtaining a Captcha

The Webportal.get_captcha() method retrieves a captcha object with an empty captcha field. The application must present the base64 image to the user and populate the captcha field with the user's answer before proceeding to authentication.
Sources: pyjiit/wrapper.py145-154 pyjiit/tokens.py4-27
Phase 1: Pretoken Check
The first authentication phase validates the username, user type, and captcha.
Request Construction

The payload dictionary contains:
{
"username": <username>,
"usertype": "S", // S = Student
"captcha": {
"captcha": <answer>,
"hidden": <id>
}
}
This payload is encrypted using serialize_payload() from pyjiit/encryption.py39-44 which:
- Converts the dictionary to JSON
- Encrypts with AES-CBC using a daily-rotated key
- Base64-encodes the result
Response Processing
The API returns an encrypted response containing registration data. The response structure includes:
- regdata: Registration information needed for Phase 2
- rejectedData: Unused field that must be removed before Phase 2
The Webportal.__hit() method handles the HTTP request and validates the response status. If the responseStatus is not "Success", a LoginError exception is raised.
Sources: pyjiit/wrapper.py111-130 pyjiit/encryption.py39-44 test_signin.py15-34
Phase 2: Token Generation
The second phase validates the password and generates the authentication token.
Request Construction
The Phase 2 payload is built from the Phase 1 response:

The modified payload contains:
- All fields from Phase 1's
responseobject (exceptrejectedData) Modulename: Set to"STUDENTMODULE"passwordotpvalue: The user's password
This payload is encrypted and sent with a fresh LocalName header to /token/generate-token1.
Response Structure
On successful authentication, the response contains a response object with:
| Field | Description |
|---|---|
regdata |
Complete registration data including token |
token |
JWT token for authenticated requests |
memberid |
Student identifier |
userid |
User identifier |
clientid |
Client identifier |
membertype |
User type identifier |
institutelist |
Array with institute information |
Sources: pyjiit/wrapper.py132-143 test_signin.py36-48
Session Creation
Upon successful Phase 2 completion, a WebportalSession object is instantiated and stored in Webportal.session.
WebportalSession Initialization

The WebportalSession constructor pyjiit/wrapper.py38-59 performs the following:
- Stores raw response in
raw_response - Extracts regdata from response
- Parses institute information from
institutelist[0] - Extracts identifiers:
memberid,userid,clientid,membertype,name - Decodes JWT token to extract expiry timestamp:
- Splits token by
.to get payload segment - Base64 decodes the payload
- Parses JSON to extract
expclaim - Converts Unix timestamp to
datetimeobject
- Splits token by
Session Headers
The get_headers() method pyjiit/wrapper.py61-68 returns headers required for authenticated requests:
{
"Authorization": "Bearer <token>",
"LocalName": <encrypted_random_string>
}
The LocalName header is regenerated for each request using generate_local_name(), which creates a unique encrypted identifier based on random characters and the current date sequence.
Sources: pyjiit/wrapper.py38-68
Authentication Error Handling
The authentication process can fail at multiple points, each raising specific exceptions.
Exception Types

Error Scenarios
| Scenario | Phase | Exception | Cause |
|---|---|---|---|
| Invalid captcha | Phase 1 | LoginError |
Incorrect captcha answer |
| Invalid username | Phase 1 | LoginError |
Username not found |
| Invalid password | Phase 2 | LoginError |
Incorrect password |
| API communication error | Either | LoginError |
Network or server issue |
The Webportal.__hit() method pyjiit/wrapper.py82-108 centralizes error handling:
- Checks if
resp["status"]is an integer401→ raisesSessionExpired - Checks if
resp["status"]["responseStatus"] != "Success"→ raises the specified exception
For student_login(), the exception parameter is set to LoginError pyjiit/wrapper.py130-139 ensuring authentication failures are properly typed.
Sources: pyjiit/wrapper.py82-143 pyjiit/exceptions.py
Complete Authentication Flow

Sources: pyjiit/wrapper.py111-143 pyjiit/wrapper.py38-68 pyjiit/encryption.py13-44 test_signin.py1-52
Implementation Details
Method Signature
The student_login() method signature pyjiit/wrapper.py111-117:
def student_login(self, username: str, password: str, captcha: Captcha) -> WebportalSession
Parameters:
username: Student username (typically enrollment number)password: Student passwordcaptcha: CompletedCaptchaobject with solved answer
Returns: WebportalSession object containing authentication token and user information
Raises: LoginError for any authentication failure
Internal Request Handler
The __hit() method pyjiit/wrapper.py82-108 is a private method that:
- Determines exception type from kwargs (defaults to
APIError) - Manages headers:
- If
authenticated=Truekwarg: usessession.get_headers() - Otherwise: generates standalone
LocalNameheader
- If
- Makes HTTP request via
requests.request() - Validates response:
- HTTP 401 status → raises
SessionExpired responseStatus != "Success"→ raises specified exception
- HTTP 401 status → raises
- Returns response dictionary if successful
For authentication, the method is called without authenticated=True, so it generates a new LocalName header for each phase.
API Endpoint Constants
The base API URL is defined as a module constant pyjiit/wrapper.py17:
API = "https://webportal.jiit.ac.in:6011/StudentPortalAPI"
Authentication endpoints:
- Captcha:
GET /token/getcaptcha - Phase 1:
POST /token/pretoken-check - Phase 2:
POST /token/generate-token1
Sources: pyjiit/wrapper.py17-143
Usage Example
from pyjiit import Webportal
# Initialize webportal client
webportal = Webportal()
# Step 1: Get captcha
captcha = webportal.get_captcha()
# Display captcha.image to user and get answer
captcha.captcha = "cfmab" # User's answer
# Step 2: Authenticate
try:
session = webportal.student_login(
username="21BCS1234",
password="mypassword",
captcha=captcha
)
print(f"Logged in as: {session.name}")
print(f"Token expires: {session.expiry}")
except LoginError as e:
print(f"Login failed: {e}")
Once student_login() succeeds, the Webportal instance's session attribute is set, enabling all @authenticated methods to be called (see Session Management).