If you are a citizen looking to sign in to Dolat-e Man, this is not the page you want: the official portal is my.gov.ir, and we have no official connection to it. This article is for technical teams at Iranian organizations who want staff or customers to sign in to an internal system with their Dolat-e Man account.
We have shipped Dolat-e Man sign-in on two real systems for a university: FanCover, a staff supplementary-insurance system, and our FanDesk service desk. What follows comes from that work, including the mistakes.
What Dolat-e Man is, from an organization's side
Dolat-e Man is Iran's national smart government services window, run by the Information Technology Organization of Iran. Citizens register once with a mobile number in their own name, their national ID and date of birth (Digiato's guide). For an organization, signing in with it means your system stops storing passwords and relies on a verified national identity instead.
Connect each system directly, or go through an organizational SSO broker?
This is the first architecture decision, and it is easy to miss. In our case the university already ran its own SSO server connected to Dolat-e Man, so neither FanCover nor FanDesk talks to Dolat-e Man directly. Each is a plain OAuth 2.0 client of the university's broker. Adding another system meant registering one more client, not doing another national integration. Vendors such as SSO Plus sell exactly this hub model with OAuth 2.0, OpenID Connect and SAML support.
The sign-in flow
- Redirect the user to the broker's
/oauth2/authorizewithclient_id,redirect_uri,response_type=code,scope=openid profileand a randomstate. - After identity verification the user comes back to your
redirect_uriwith a one-timecodeand the samestate. - Your server exchanges the code for an access token at
/oauth2/token, usingclient_secret. Never do this step in the browser. - Fetch the user profile with that token and create your own session.
In our integration the profile included national ID, first and last name, father's name, mobile, gender, date of birth, birth certificate number, postal code, province and city. Your broker and scopes may return less. Store only what you need.
Security details worth getting right
- Keep
stateone-time-use with an expiry. We store it in the database with a TTL index so it works across multiple workers. client_secretstays on the server.- Register an exact
redirect_uri, no wildcards. - Put your own session token in an httpOnly, Secure cookie, not localStorage.
The lesson that cost us: identity is not authorization
Dolat-e Man proves who someone is. It does not say whether they are allowed into your system. In the insurance system, after a successful sign-in we checked the national ID against a personnel list built from an old HR export, while the authoritative list of insured staff was maintained live by the system's own admins. A group of real employees, fully verified by Dolat-e Man, were told they were not university staff. The fix was to also count the insurance eligibility list, so admins can unblock someone from the panel without a re-import or redeploy. We also found a few nine-digit national IDs: a spreadsheet had cast them to numbers and dropped the leading zero.
Decide which list, in which system, decides who gets in before you switch sign-in on, and always store national IDs as ten-character strings.
Don't forget existing accounts
We match users by national ID, but some older staff accounts had been created without one, using the national ID as the username. Matching only on national ID would have created a duplicate customer account for them and cut them off from the tickets assigned to their real account. The fix: fall back to the username, backfill the national ID, and only fill empty fields from the SSO profile. Never overwrite roles, permissions or admin-set names.
For the why behind national SSO in institutions, see this piece, and for why isolation matters for sensitive staff data, this one.