Logging in
Introduction
The Eagle Eye Networks API v3 uses the Authorization Code pattern from the OAuth 2.0 standard for authentication. The pattern requires a user to sign in and grant an application access to their Eagle Eye Networks resources. It keeps credentials and tokens secure by sending the user through the Eagle Eye Networks login and consent experience, then returning control to your application with a short-lived authorization code that your backend exchanges for tokens.
This process allows the the same application to be used by multiple end users. Each user signs in with their own Eagle Eye Networks credentials and grants the application access to their own resources. The application uses the tokens it receives to make API calls on behalf of the signed-in user.
This section walks through that end-to-end process—how to generate the authorization request, what happens during login and consent, and how your application completes the exchange to obtain an access token. It also calls out the most important detail to get right: your redirect URL, which must be registered and must match exactly, because it is the handoff point where the authentication server returns the user (and the authorization code) back to your application.
Requesting User Authorization
Before your application can access Eagle Eye Networks resources on behalf of a user, the user must first authorize your application. This is done by redirecting the user to Eagle Eye's authorization server with a URL that includes your application's client ID and the redirect URL where the user will be sent after granting permission.
You can think of this process as having two parts:
- Phase 1: The user logs in and approves your application to access their resources.
- Phase 2: Your application exchanges the authorization code for an access token and refresh token.
NoteOnly the initial authorization requires human action. Once authorization has been given, the machine-to-machine authorization can be completed using a refresh token.
Phase 1: Constructing the Authorization Request
To initiate the authorization process, your application must construct a URL that includes the necessary parameters. This URL will be used to redirect the user to the Eagle Eye authorization server.
The following parameters are required:
client_id: Your application's client ID.response_type: Set this tocodeto indicate that you are requesting an authorization code.redirect_uri: The URL to which the user will be redirected after granting permission. This must match the registered redirect URI exactly.scope: The permissions your application is requesting. For example,vms.allto access all video management system resources.
Here's an example of how you might construct the authorization URL:
getAuthUrl(): string {
const authBaseUrl = 'https://auth.eagleeyenetworks.com/oauth2/authorize';
const params = {
response_type: 'code',
scope: 'vms.all',
client_id: this.clientId,
redirect_uri: this.redirectUri
};
const queryString = new URLSearchParams(params).toString();
return `${authBaseUrl}?${queryString}`;
}When the user is redirected to this URL, they will be presented with the Eagle Eye login screen. After logging in, they will be asked to approve your application to access their resources. If they approve, they will be redirected back to your specified redirect_uri with an authorization code included as a query parameter. You can then use this code to complete the authorization process in Phase 2.
Phase 2: Authorization Code Exchange
Once the user has authorized your application and you have received the authorization code, you can exchange this code for an access token and refresh token. This is done by making a POST request to the Eagle Eye token endpoint.
POST https://auth.eagleeyenetworks.com/oauth2/token
The request must include the following parameters:
grant_type: Set this toauthorization_code.code: The authorization code you received from the previous step.redirect_uri: The same redirect URI used in the authorization request.scope: The same scope used in the authorization request.
You must authenticate the request with your application's Client Credentials. The Authorization header uses basic access authentication with the client_id and client_secret serving as the username and password. The client_id and client_secret must be encoded with Base64 and joined by a single colon.
This process must be completed within 5 minutes of receiving the authorization code, or the code will expire. In addition, the POST request must originate from the same redirect URI specified in the initial authorization request.
You can see an example of this request below:
curl --request 'POST' \
--url 'https://auth.eagleeyenetworks.com/oauth2/token' \
--header 'accept: application/json' \
--header 'content-type: application/x-www-form-urlencoded' \
--header 'authorization: Y2xpZW50SWQ6Y2xpZW50U2VjcmV0' \
--data '
{
"grant_type": "authorization_code",
"scope": "vms.all",
"code": "{code}",
"redirect_uri": "{URI with http(s)://}"
}
'import requests
url = "https://auth.eagleeyenetworks.com/oauth2/token"
data = {
"grant_type": "authorization_code",
"scope": "vms.all",
"code": "{code}",
"redirect_uri": "{URI with http(s)://}"
}
headers = {
"accept": "application/json",
"content-type": "application/x-www-form-urlencoded"
}
response = requests.post(
url,
headers=headers,
auth=(
'CLIENT_ID',
'CLIENT_SECRET'
),
data=data
)
print(response.text)package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/url"
"io"
)
func main() {
url := "https://auth.eagleeyenetworks.com/oauth2/token"
data := url.Values{}
data.Set("grant_type", "authorization_code")
data.Set("scope", "vms.all")
data.Set("code", code)
data.Set("redirect_uri", fmt.Sprintf("http://%s:%d", hostName, port))
req, _ := http.NewRequest("POST", url, bytes.NewBufferString(data.Encode()))
req.Header.Add("accept", "application/json")
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.SetBasicAuth(clientId, clientSecret)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}
Important
- Make sure to add the
accept application/jsonheader to the HTTPPOSTrequest.- The
content-typeheader should be set toapplication/x-www-form-urlencoded.- Make sure the redirect URI parameter is the same as in the previous request, otherwise the request fails.
- If a refresh token is required, make sure you perform this API call with your application server, and not in the browser. If you perform this API call in the browser, you will expose your API key and the user's refresh token.
- The Authorization header uses basic authentication. Make sure to encode your
\<client_id>:\<client_secret>with Base64.- All parameters must be sent in the request body as JSON. Query parameters are not supported.
If the request is successful, the authentication server response will include an access token and a refresh token. The access token can be used to authenticate API requests on behalf of the user, while the refresh token can be used to obtain new access tokens when the current one expires.
The access token has a maximum lifespan of 12 hours. The refresh token is longer lasting and can be used to generate a new access token without requiring the user to sign in again. This can also be used for mobile applications that can store the refresh token in a keychain.
Example Response:
{
"access_token": "eyJraWQiOiI2ODYxYjBjYS0wZjI2LTExZWQtODYxZC0wMjQyYWMxMjAwMDIiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJjYTBmNjFhYiIsImF1ZCI6InZtcy5hcGkiLCJpc3MiOiJ2bXMuYXV0aC52MSIsInZtc19hY2NvdW50IjoiMDAwMDExMDYiLCJleHAiOjE2NjAzNjA0ODksImlhdCI6MTY2MDMxNzI4OSwianRpIjoiODJlNWMyMDQ1OTM1OTczNGYyOTU4NjlkZDhlYzIyMDMiLCJjbGllbnRfaWQiOiJCTVRPLVRFU1QiLCJ2bXNfY2x1c3RlciI6ImMwMDAifQ.JuUiozX0XMKz0kuFJTGsNFRdxOKNV4R6iRW8t6N-FpElU4sWBLhyioIot3dV2GFnHWpY5wzdFWuwVxuSvYRwhPGs6sYt4Uo0pWsrI6a9WylyavacjSmLuljdnplUzKuoB3BzohCrQGCUmiMFJ8eA4jNZnViuQ7ouKRoM4mbTSdwy_YUoNm4F7GDBiHp6TEoMFscUDlWzC-GJwVMklRGAAw_9OTTl-CGWt-CngqL1K-2Qt-3iS0WY1Jpal3-YMlJ1FVTDDuCgVIluemaH2g7ScEOM5vEnpj31H_6Gu7R9NB5CDzLaEDm2MHRJThId1-3kyhreG3Ux-WV2TAOzGbLnkg",
"expires_in": 43198,
"httpsBaseUrl": {
"hostname": "api.c001.eagleeyenetworks.com",
"port": 443
},
"refresh_token": "w1P0nwA7NEZmo5tEd76cco3y5bi4Js6QNgZsXnFNBDRepnJmA2F73tGJ4G_eA0WttI_8xsovsFLvd5uOUayqrNwu7PZ1SH0DAWVZ3",
"scope": "vms.all",
"token_type": "Bearer"
}Refresh Token Authentication
Once the refresh token is obtained, it can be used for logging in again. Doing so will generate a new access token and a new refresh token. Refreshing the access token in this way does not require any user interaction.
ImportantIt is recommended to store the refresh token in a secure place. The refresh token should never be exposed.
Procedure
With a valid refresh token, an access token can be generated by sending a POST request to the oauth2/token endpoint. The request will be authenticated by using your Client Credentials via HTTP basic authentication. In this method, encode your <client_id>:<secret> in Base64.
See the following example for logging in using the refresh token
curl --location --request POST 'https://auth.eagleeyenetworks.com/oauth2/token' \
--header 'Accept: application/json' \
--header 'content-type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic Y2xpZW50SWQ6Y2xpZW50U2VjcmV0' \
--data '
{
"grant_type": "refresh_token",
"scope": "vms.all",
"refresh_token": "P1m_7oFP2Ful4yVGh5Z9QcQlGygiMaz0uah3QvqUbZpfufBSmpr9P6dPvlBP_1EhKS1WjyUcFGxQZrEewn62X1Og0Ww1ns3wA0ah5jJHowabYlHoYS0DAg7QUE6_mZFT"
}
'import requests
url = "https://auth.eagleeyenetworks.com/oauth2/token"
data = {
"grant_type": "refresh_token",
"scope": "vms.all",
"refresh_token": "P1m_7oFP2Ful4yVGh5Z9QcQlGygiMaz0uah3QvqUbZpfufBSmpr9P6dPvlBP_1EhKS1WjyUcFGxQZrEewn62X1Og0Ww1ns3wA0ah5jJHowabYlHoYS0DAg7QUE6_mZFT"
}
headers = {
"accept": "application/json",
"content-type": "application/x-www-form-urlencoded"
}
response = requests.post(
url,
headers=headers,
auth=(
'CLIENT_ID',
'CLIENT_SECRET'
),
data=data
)
print(response.text)package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/url"
"io"
)
func main() {
url := "https://auth.eagleeyenetworks.com/oauth2/token"
data := url.Values{}
data.Set("grant_type", "refresh_token")
data.Set("scope", "vms.all")
data.Set("refresh_token", "P1m_7oFP2Ful4yVGh5Z9QcQlGygiMaz0uah3QvqUbZpfufBSmpr9P6dPvlBP_1EhKS1WjyUcFGxQZrEewn62X1Og0Ww1ns3wA0ah5jJHowabYlHoYS0DAg7QUE6_mZFT")
req, _ := http.NewRequest("POST", url, bytes.NewBufferString(data.Encode()))
req.Header.Add("accept", "application/json")
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.SetBasicAuth(clientId, clientSecret)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}Response:
{
"access_token": "eyJraWQiOiI2ODYxYjBjYS0wZjI2LTExZWQtODYxZC0wMjQyYWMxMjAwMDIiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJjYTBmNjFhYiIsImF1ZCI6InZtcy5hcGkiLCJpc3MiOiJ2bXMuYXV0aC52MSIsInZtc19hY2NvdW50IjoiMDAwMDExMDYiLCJleHAiOjE2NjAzNjA0ODksImlhdCI6MTY2MDMxNzI4OSwianRpIjoiODJlNWMyMDQ1OTM1OTczNGYyOTU4NjlkZDhlYzIyMDMiLCJjbGllbnRfaWQiOiJCTVRPLVRFU1QiLCJ2bXNfY2x1c3RlciI6ImMwMDAifQ.JuUiozX0XMKz0kuFJTGsNFRdxOKNV4R6iRW8t6N-FpElU4sWBLhyioIot3dV2GFnHWpY5wzdFWuwVxuSvYRwhPGs6sYt4Uo0pWsrI6a9WylyavacjSmLuljdnplUzKuoB3BzohCrQGCUmiMFJ8eA4jNZnViuQ7ouKRoM4mbTSdwy_YUoNm4F7GDBiHp6TEoMFscUDlWzC-GJwVMklRGAAw_9OTTl-CGWt-CngqL1K-2Qt-3iS0WY1Jpal3-YMlJ1FVTDDuCgVIluemaH2g7ScEOM5vEnpj31H_6Gu7R9NB5CDzLaEDm2MHRJThId1-3kyhreG3Ux-WV2TAOzGbLnkg",
"expires_in": 25734,
"httpsBaseUrl": {
"hostname": "api.c001.eagleeyenetworks.com",
"port": 443
},
"refresh_token": "Mp4k-iSQYwZ3074_e5LUJ2A01BBm5QZ6H5hE_PrGsK5edxptWsgpXQ2QxfVwrqi8MC6jhdY72y5rWA1-5znkb_QSqfF0GXLYz9m1DrUYPQ2dJRouBrK2lv5xYZerV-7D",
"scope": "vms.all",
"token_type": "Bearer"
}Token Life Cycle
Refresh tokens are rotated by default. This means that each time you use a refresh token to obtain a new access token, a new refresh token is also issued. Both the old refresh token and the access token will be invalidated by this process.
Each set of refresh tokens have a maximum lifespan of 90 days starting from the moment that Phase 1 of the authentication process is completed. However, if a refresh token is unused, it will expire after 14 days. This means that if you do not use the refresh token to obtain a new access token within 14 days, it will become invalid. If instead, you use the refresh token to obtain a new access token, you will receive a new refresh token with an additional 14 days of validity. This process continues until the maximum lifespan of 90 days is reached.
When the latest refresh token expires, the user must log in again to obtain a new refresh token. This is done by repeating the User Authorization process using the Code Authorization flow.
Avoid Asynchronous RefreshingWhen implementing the refresh token flow, it is important to avoid making asynchronous calls to refresh tokens. This can lead to race conditions and unexpected behavior in your application. Ensure that your application handles token refreshing in a synchronous manner with a mutex or similar locking mechanism.
M2M Authentication using Non-Rotating Refresh Tokens
While we highly recommend architecting your application to accommodate refresh token rotation, Eagle Eye Networks provides an option to use a non-rotating, permanent refresh token. Unlike the standard refresh tokens that expire after 90 days, this permanent refresh token does not have an expiration date.
Token Life Cycle
The permanent refresh token can be used indefinitely to obtain new access tokens without requiring the user to log in again. This is particularly useful for applications that need to maintain long-term access without user intervention.
When you use the permanent refresh token to obtain an access token, you will receive a new access token with a maximum lifespan of 12 hours. However, if there is still an active access token from that refresh token, the currently active access token will be returned. In this case, the expiration time of the access token will not be changed.
No Forced RotationUnlike with the standard refresh tokens, non-rotating refresh tokens do not force the expiration of the corresponding access token when the refresh operation is performed. A new access token will only be returned after the latest access token has expired. Therefore, it is recommended to use retry logic in your application to handle the case when the access token is expired, and a new one needs to be requested.
Activating Non-Rotating Refresh Tokens
To enable this feature for your Client Credentials, contact [email protected], and our support team will assist you with this process.
OAuth Implementation Example
The following recipe demonstrates how to implement OAuth2 in multiple programming languages.
Updated 15 days ago