From 99c819caebe1e64c11cc9e6867b175a82e59762d Mon Sep 17 00:00:00 2001 From: "s.hajizadeh" Date: Tue, 30 Jun 2026 11:51:40 +0330 Subject: [PATCH] feat(fanavaran): add auth token script Why: - Manual curl token setup was error-prone and allowed stale appToken reuse. Changes: - Add a script that accepts tejaratno or parsian, calls GetAppToken, then Login. - Document the script flow and fill known curl variables from the codebase. Impact: - Users can generate fresh Fanavaran tokens without manually copying multi-step curl commands. --- docs/external-api-curls.md | 192 +++++++++++++++++++++++++++++++++---- scripts/fanavaran-auth.sh | 143 +++++++++++++++++++++++++++ 2 files changed, 314 insertions(+), 21 deletions(-) create mode 100755 scripts/fanavaran-auth.sh diff --git a/docs/external-api-curls.md b/docs/external-api-curls.md index 65fcf5c..c8f038b 100644 --- a/docs/external-api-curls.md +++ b/docs/external-api-curls.md @@ -1,7 +1,9 @@ # External API Curl Guide This file documents outbound HTTP calls made by the app or maintenance scripts. -Use placeholder values for secrets, tokens, IDs, plate values, and payloads before running any curl. +Client credentials that are hardcoded in the codebase are filled in below. Keep +placeholders only for runtime data such as national codes, plate values, tokens +returned by login calls, and payload files. ## Common Notes @@ -32,29 +34,73 @@ Used by: 2. Login with `appToken` to get `authenticationToken`. 3. Call lookup, policy inquiry, or submit endpoint with `authenticationToken`, `CorpId`, `ContractId`, and `Location`. +### Auth Script + +Use this when you only need fresh Fanavaran tokens and do not want to copy the +curl commands manually: + +```sh +scripts/fanavaran-auth.sh tejaratno +scripts/fanavaran-auth.sh parsian +``` + +The script stores raw responses and reusable variables under +`files/fanavaran-auth//`. For example: + +```sh +source files/fanavaran-auth/tejaratno/tokens.env +curl -X GET "$FANAVARAN_BIME_URL/car/base-info/accident-causes" \ + -H "authenticationToken: $AUTHENTICATION_TOKEN" \ + -H "CorpId: $CORP_ID" \ + -H "ContractId: $CONTRACT_ID" \ + -H "Location: $LOCATION" \ + -H "Content-Type: application/json" +``` + ### Tenant Credentials The app supports these Fanavaran client profiles: | Client | appname | secret | userName | password | CorpId | ContractId | Location | | --- | --- | --- | --- | --- | --- | --- | --- | -| tejaratno | from `src/core/config/fanavaran-client.config.ts` | hardcoded in source | hardcoded in source | hardcoded in source | `3539` | `263` | `100` | -| parsian | from `src/core/config/fanavaran-client.config.ts` | hardcoded in source | hardcoded in source | hardcoded in source | `543` | `28` | `210050` | +| tejaratno | `fanhab` | `5Fa@N#A2B` | `fanhabUser` | `Fan#@2U$3er` | `3539` | `263` | `100` | +| parsian | `ParsianService` | `P@r30@n$erv!ce` | `ParsianServiceUser` | `P@r30@n123` | `543` | `28` | `210050` | -Set them as shell variables before running: +Set the client variables before running. These values come from +`src/core/config/fanavaran-client.config.ts` and match +`src/claim-request-management/claim-request-management.service.ts`. + +Tejaratno: ```sh -APP_NAME="" -APP_SECRET="" -FANAVARAN_USERNAME="" -FANAVARAN_PASSWORD="" -CORP_ID="" -CONTRACT_ID="" -LOCATION="" +FANAVARAN_CLIENT="tejaratno" +APP_NAME='fanhab' +APP_SECRET='5Fa@N#A2B' +FANAVARAN_USERNAME='fanhabUser' +FANAVARAN_PASSWORD='Fan#@2U$3er' +CORP_ID='3539' +CONTRACT_ID='263' +LOCATION='100' +``` + +Parsian: + +```sh +FANAVARAN_CLIENT="parsian" +APP_NAME='ParsianService' +APP_SECRET='P@r30@n$erv!ce' +FANAVARAN_USERNAME='ParsianServiceUser' +FANAVARAN_PASSWORD='P@r30@n123' +CORP_ID='543' +CONTRACT_ID='28' +LOCATION='210050' ``` ### 1. Get App Token +The app sends an empty string body, deletes `Content-Type`, and keeps +`Content-Length: 0`. + ```sh curl -i -X POST "$FANAVARAN_BASE_URL/EITAuthentication/GetAppToken" \ -H "appname: $APP_NAME" \ @@ -65,11 +111,21 @@ curl -i -X POST "$FANAVARAN_BASE_URL/EITAuthentication/GetAppToken" \ The token is returned in a response header named `appToken` or `apptoken`. ```sh -APP_TOKEN="" +curl -sS -D /tmp/fanavaran-app-token.headers -o /tmp/fanavaran-app-token.body \ + -X POST "$FANAVARAN_BASE_URL/EITAuthentication/GetAppToken" \ + -H "appname: $APP_NAME" \ + -H "secret: $APP_SECRET" \ + -H "Content-Length: 0" +APP_TOKEN="$(awk -F': ' 'tolower($1)=="apptoken" {gsub(/\r/,"",$2); print $2}' /tmp/fanavaran-app-token.headers)" +printf 'APP_TOKEN=%s\n' "$APP_TOKEN" ``` ### 2. Login +Use the `APP_TOKEN` returned by the immediately previous GetAppToken request. +Do not reuse an old app token pasted from logs or another machine; the app does +not do that. + ```sh curl -i -X POST "$FANAVARAN_BASE_URL/EITAuthentication/Login" \ -H "appToken: $APP_TOKEN" \ @@ -81,7 +137,95 @@ curl -i -X POST "$FANAVARAN_BASE_URL/EITAuthentication/Login" \ The token is returned in a response header or body field named `authenticationToken`, `authenticationtoken`, or `authentication_token`. ```sh -AUTHENTICATION_TOKEN="" +curl -sS -D /tmp/fanavaran-login.headers -o /tmp/fanavaran-login.body \ + -X POST "$FANAVARAN_BASE_URL/EITAuthentication/Login" \ + -H "appToken: $APP_TOKEN" \ + -H "userName: $FANAVARAN_USERNAME" \ + -H "password: $FANAVARAN_PASSWORD" \ + -H "Content-Length: 0" +AUTHENTICATION_TOKEN="$(awk -F': ' 'tolower($1)=="authenticationtoken" {gsub(/\r/,"",$2); print $2}' /tmp/fanavaran-login.headers)" +if [ -z "$AUTHENTICATION_TOKEN" ]; then + AUTHENTICATION_TOKEN="$(node -e 'const fs=require("fs"); const body=fs.readFileSync("/tmp/fanavaran-login.body","utf8"); try { const json=JSON.parse(body); console.log(json.authenticationToken || json.authenticationtoken || json.authentication_token || ""); } catch { console.log(""); }')" +fi +printf 'AUTHENTICATION_TOKEN=%s\n' "$AUTHENTICATION_TOKEN" +``` + +If login returns `نام کاربر یا رمز عبور صحیح نیست` for `tejaratno`, first check +that `APP_TOKEN` was generated with `appname: fanhab` and `secret: 5Fa@N#A2B` in +the same sequence. The runtime code calls `GetAppToken` first, then passes that +fresh header value to `Login`; it does not use a static value such as +`182197f6-7b41-47b4-9b18-5bfcbc027f2e`. + +### Ready-To-Run Auth Sequences + +Tejaratno: + +```sh +FANAVARAN_BASE_URL="https://apimanager.iraneit.com/BimeApiManager/api" +FANAVARAN_BIME_URL="$FANAVARAN_BASE_URL/BimeApi/v2.0" +FANAVARAN_CLIENT="tejaratno" +APP_NAME='fanhab' +APP_SECRET='5Fa@N#A2B' +FANAVARAN_USERNAME='fanhabUser' +FANAVARAN_PASSWORD='Fan#@2U$3er' +CORP_ID='3539' +CONTRACT_ID='263' +LOCATION='100' + +curl -sS -D /tmp/fanavaran-app-token.headers -o /tmp/fanavaran-app-token.body \ + -X POST "$FANAVARAN_BASE_URL/EITAuthentication/GetAppToken" \ + -H "appname: $APP_NAME" \ + -H "secret: $APP_SECRET" \ + -H "Content-Length: 0" +APP_TOKEN="$(awk -F': ' 'tolower($1)=="apptoken" {gsub(/\r/,"",$2); print $2}' /tmp/fanavaran-app-token.headers)" + +curl -sS -D /tmp/fanavaran-login.headers -o /tmp/fanavaran-login.body \ + -X POST "$FANAVARAN_BASE_URL/EITAuthentication/Login" \ + -H "appToken: $APP_TOKEN" \ + -H "userName: $FANAVARAN_USERNAME" \ + -H "password: $FANAVARAN_PASSWORD" \ + -H "Content-Length: 0" +AUTHENTICATION_TOKEN="$(awk -F': ' 'tolower($1)=="authenticationtoken" {gsub(/\r/,"",$2); print $2}' /tmp/fanavaran-login.headers)" +if [ -z "$AUTHENTICATION_TOKEN" ]; then + AUTHENTICATION_TOKEN="$(node -e 'const fs=require("fs"); const body=fs.readFileSync("/tmp/fanavaran-login.body","utf8"); try { const json=JSON.parse(body); console.log(json.authenticationToken || json.authenticationtoken || json.authentication_token || ""); } catch { console.log(""); }')" +fi + +printf 'APP_TOKEN=%s\nAUTHENTICATION_TOKEN=%s\n' "$APP_TOKEN" "$AUTHENTICATION_TOKEN" +``` + +Parsian: + +```sh +FANAVARAN_BASE_URL="https://apimanager.iraneit.com/BimeApiManager/api" +FANAVARAN_BIME_URL="$FANAVARAN_BASE_URL/BimeApi/v2.0" +FANAVARAN_CLIENT="parsian" +APP_NAME='ParsianService' +APP_SECRET='P@r30@n$erv!ce' +FANAVARAN_USERNAME='ParsianServiceUser' +FANAVARAN_PASSWORD='P@r30@n123' +CORP_ID='543' +CONTRACT_ID='28' +LOCATION='210050' + +curl -sS -D /tmp/fanavaran-app-token.headers -o /tmp/fanavaran-app-token.body \ + -X POST "$FANAVARAN_BASE_URL/EITAuthentication/GetAppToken" \ + -H "appname: $APP_NAME" \ + -H "secret: $APP_SECRET" \ + -H "Content-Length: 0" +APP_TOKEN="$(awk -F': ' 'tolower($1)=="apptoken" {gsub(/\r/,"",$2); print $2}' /tmp/fanavaran-app-token.headers)" + +curl -sS -D /tmp/fanavaran-login.headers -o /tmp/fanavaran-login.body \ + -X POST "$FANAVARAN_BASE_URL/EITAuthentication/Login" \ + -H "appToken: $APP_TOKEN" \ + -H "userName: $FANAVARAN_USERNAME" \ + -H "password: $FANAVARAN_PASSWORD" \ + -H "Content-Length: 0" +AUTHENTICATION_TOKEN="$(awk -F': ' 'tolower($1)=="authenticationtoken" {gsub(/\r/,"",$2); print $2}' /tmp/fanavaran-login.headers)" +if [ -z "$AUTHENTICATION_TOKEN" ]; then + AUTHENTICATION_TOKEN="$(node -e 'const fs=require("fs"); const body=fs.readFileSync("/tmp/fanavaran-login.body","utf8"); try { const json=JSON.parse(body); console.log(json.authenticationToken || json.authenticationtoken || json.authentication_token || ""); } catch { console.log(""); }')" +fi + +printf 'APP_TOKEN=%s\nAUTHENTICATION_TOKEN=%s\n' "$APP_TOKEN" "$AUTHENTICATION_TOKEN" ``` ### 3A. Lookup Endpoints @@ -167,6 +311,8 @@ Default base URL: ```sh TEJARAT_INQUIRY_BASE_URL="${TEJARAT_INQUIRY_BASE_URL:-http://82.99.202.245:3027}" +TEJARAT_INQUIRY_EMAIL='xxx@example.com' +TEJARAT_INQUIRY_PASSWORD='123321' ``` Used by `src/sand-hub/sand-hub.service.ts` for third-party plate and car-body plate inquiries when ESG is not selected. @@ -311,8 +457,10 @@ Used by `src/sand-hub/sand-hub.service.ts` for legacy inquiry flows. Environment: ```sh -SANHUB_URL_LOGIN="" -SANHUB_BASE_URL="" +SANHUB_BASE_URL='http://82.99.202.245:3027' +SANHUB_URL_LOGIN='http://82.99.202.245:3027/user/login' +SANHUB_USERNAME='default@admin.com' +SANHUB_PASSWORD='123321' ``` ### Sequence @@ -415,7 +563,7 @@ curl -X POST "$SANHUB_BASE_URL/sheba/sheba-tejaratno" \ Used by `src/claim-request-management/claim-request-management.service.ts`. ```sh -MAP_IR_API_KEY="" +MAP_IR_API_KEY='eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImI5ZDZjMThkNDRjZjc2OWI2Yjk1ODcyMGFjYmEzMmRiN2NhZjg0Zjk4OTRlMjZiZDg0Yzg3YjVlMzhlMTAyZDlkMWYxOGM5NjNmOTk4YjY2In0.eyJhdWQiOiIyMTcxOCIsImp0aSI6ImI5ZDZjMThkNDRjZjc2OWI2Yjk1ODcyMGFjYmEzMmRiN2NhZjg0Zjk4OTRlMjZiZDg0Yzg3YjVlMzhlMTAyZDlkMWYxOGM5NjNmOTk4YjY2IiwiaWF0IjoxNjgwNjA4NTkxLCJuYmYiOjE2ODA2MDg1OTEsImV4cCI6MTY4MzIwMDU5MSwic3ViIjoiIiwic2NvcGVzIjpbImJhc2ljIl19.rTviLd8b5yTHUDa3ODZyva593eMnL0d3XPg3sKkZxMOf_jNIH6lFQyIfbId-wsd1EAdsOdsL3CME_Y8t332PWJbxMNgnEq4Rf2IkClkvkSx6Sb5_4bmlhBM75zw2SmccvgbFUn4xkTOw0FT4vABC2Y3-MKctjMpmO8QOrVULSKt4psrmQhr7hBu7YRDnAAEc6muZ1VpRvdB1kqNKddoSIrfDaq6aDRJ-BNbGRAaFFvP_kH4cgSCKV4dU0TknL3mRKUiVy6_TDkjtzAN8fE2wsdvNo2pGTJPzKFsR2ipgGNTvB__g3bOnVpKsgFXPBH0e_Qa7ff1tZ3VGWy3jRNh9Lg' LAT="35.6892" LON="51.3890" @@ -431,7 +579,7 @@ curl -X GET "https://map.ir/fast-reverse?lat=$LAT&lon=$LON" \ Used by `src/sms-orchestration/provider/kavenegar.service.ts`. ```sh -SMS_API_KEY="" +SMS_API_KEY='75776C717969412B4B52306A5956462F4A714E6F6C65544D6A2B654B7566786E' KAVENEGAR_BASE_URL="https://api.kavenegar.com/v1/$SMS_API_KEY" ``` @@ -462,9 +610,9 @@ Used by `src/sms-orchestration/provider/parsian-sms.gateway.ts`. `PARSIAN_SMS_URL` is expected to already include the provider URL prefix and query key before receptor. The app appends `=&Message=`. ```sh -PARSIAN_SMS_URL="" -PARSIAN_API_KEY="" -PARSIAN_BASIC_TOKEN="" +PARSIAN_SMS_URL='https://apigateway.parsianinsurance.com/api/SendSMS?ReceiverNumbers' +PARSIAN_API_KEY='be988c9c-dbd6-494e-9c04-944ecc6426bf' +PARSIAN_BASIC_TOKEN='UGFyc2lhbkFQSTpQYXJzaWFuQHBpMjI=' RECEPTOR="09120000000" MESSAGE="Hello" @@ -494,7 +642,9 @@ curl -X GET "${CW_URL}price?hamrah" 3. `POST $AI_URL_V2/services/car-damage/detector?version=ai-v7` ```sh -AI_URL_V2="" +AI_URL_V2='https://ai-gw.ittalie.ir' +AI_USERNAME='yara@gmail.io' +AI_PASSWORD='123321' curl -X POST "$AI_URL_V2/auth/login" \ -H "Content-Type: application/json" \ diff --git a/scripts/fanavaran-auth.sh b/scripts/fanavaran-auth.sh new file mode 100755 index 0000000..5435ff9 --- /dev/null +++ b/scripts/fanavaran-auth.sh @@ -0,0 +1,143 @@ +#!/usr/bin/env bash +set -euo pipefail + +usage() { + cat <<'USAGE' +Usage: + scripts/fanavaran-auth.sh + +Calls Fanavaran GetAppToken, then Login with the returned appToken. +Outputs the appToken and authenticationToken, and writes raw responses to: + files/fanavaran-auth// + +Optional: + FANAVARAN_BASE_URL can override the default API Manager base URL. +USAGE +} + +client="${1:-}" +if [[ -z "$client" || "$client" == "-h" || "$client" == "--help" ]]; then + usage + exit 0 +fi + +case "$client" in + tejaratno) + app_name='fanhab' + app_secret='5Fa@N#A2B' + fanavaran_username='fanhabUser' + fanavaran_password='Fan#@2U$3er' + corp_id='3539' + contract_id='263' + location='100' + ;; + parsian) + app_name='ParsianService' + app_secret='P@r30@n$erv!ce' + fanavaran_username='ParsianServiceUser' + fanavaran_password='P@r30@n123' + corp_id='543' + contract_id='28' + location='210050' + ;; + *) + printf 'Unknown Fanavaran client: %s\n\n' "$client" >&2 + usage >&2 + exit 1 + ;; +esac + +base_url="${FANAVARAN_BASE_URL:-https://apimanager.iraneit.com/BimeApiManager/api}" +auth_dir="files/fanavaran-auth/$client" +mkdir -p "$auth_dir" + +app_token_headers="$auth_dir/get-app-token.headers" +app_token_body="$auth_dir/get-app-token.body.json" +login_headers="$auth_dir/login.headers" +login_body="$auth_dir/login.body.json" +tokens_file="$auth_dir/tokens.env" + +extract_header() { + local header_name="$1" + local header_file="$2" + awk -F': ' -v wanted="$header_name" ' + tolower($1) == tolower(wanted) { + gsub(/\r/, "", $2) + print $2 + exit + } + ' "$header_file" +} + +extract_authentication_token_from_body() { + local body_file="$1" + node -e ' +const fs = require("fs"); +const path = process.argv[1]; +const body = fs.existsSync(path) ? fs.readFileSync(path, "utf8") : ""; +try { + const json = JSON.parse(body || "{}"); + console.log(json.authenticationToken || json.authenticationtoken || json.authentication_token || ""); +} catch { + console.log(""); +} +' "$body_file" +} + +printf 'Fanavaran client: %s\n' "$client" +printf 'Base URL: %s\n\n' "$base_url" + +printf '1. Calling GetAppToken...\n' +curl -sS -D "$app_token_headers" -o "$app_token_body" \ + -X POST "$base_url/EITAuthentication/GetAppToken" \ + -H "appname: $app_name" \ + -H "secret: $app_secret" \ + -H "Content-Length: 0" + +app_token="$(extract_header "apptoken" "$app_token_headers")" +if [[ -z "$app_token" ]]; then + printf 'Failed to extract appToken from %s\n' "$app_token_headers" >&2 + printf 'Response body is saved at %s\n' "$app_token_body" >&2 + exit 1 +fi + +printf '2. Calling Login...\n' +curl -sS -D "$login_headers" -o "$login_body" \ + -X POST "$base_url/EITAuthentication/Login" \ + -H "appToken: $app_token" \ + -H "userName: $fanavaran_username" \ + -H "password: $fanavaran_password" \ + -H "Content-Length: 0" + +authentication_token="$(extract_header "authenticationtoken" "$login_headers")" +if [[ -z "$authentication_token" ]]; then + authentication_token="$(extract_authentication_token_from_body "$login_body")" +fi + +if [[ -z "$authentication_token" ]]; then + printf 'Failed to extract authenticationToken from login response.\n' >&2 + printf 'Headers: %s\n' "$login_headers" >&2 + printf 'Body: %s\n' "$login_body" >&2 + exit 1 +fi + +cat > "$tokens_file" <