Logging in
Introduction
The Eagle Eye Networks API v3 uses the OAuth2 "Authorization code" grant type to authenticate a user. This can be used to connect an Eagle Eye user with a third-party system.
The goal of this guide is to explain how to authenticate using the OAuth2 "Authorization code" grant type to get a set of tokens. Third-party applications can use these tokens to authenticate API requests to the Eagle Eye Networks Video API Platform. When authenticating requests in this manner, the application acts on behalf of an end user.
If you would rather skip the guide and get the access token to use in Postman or any other API client, go to My Application.
Phase 1: Granting access to a third-party app
Important
Eagle Eye users need to explicitly grant access to third-party applications. This procedure cannot be automated.
Note
Only the initial authorization (Phase 1) requires human action, the machine-to-machine authorization (Phase 2) can be fully automated.
Before you begin
- Create your application in the Eagle Eye Developer Portal and obtain your client ID and client secret. For more instructions, see the Client Credentials page.
- Add your application's redirect URI to the OAuth whitelist. You must the protocol (
https\://
orhttp\://
) in the entry. For testing with localhost IP, it has to be, for example:<http://127.0.0.1:3333>
. To whitelist a redirect URI please email [email protected].
Procedure
- Make the request as HTTP
POST
or HTTPGET
, or go to your browser of choice. - Redirect the user to
auth.eagleeyenetworks.com
, to the login screen with the URL shown below:
'https://auth.eagleeyenetworks.com/oauth2/authorize?scope=vms.all&client_id={clientId}&response_type=code&redirect_uri={URI with http(s)://}' /

The {client_id}
value should be the client ID, part of the Client Credentials. Always ensure that your client secret remains private.
Important
The redirect URI must exactly match the one in the example (
<http://127.0.0.1:3333>
). Since whitelist checking is based on string comparison, any other formats, such as<https://127.0.0.1:3333>
orhttp://localhost:3333
or127.0.0.1:3333/
will not work.
- If the user is not yet logged in, they need to log in to Eagle Eye Networks on the following screen:
After logging in, the user is redirected to the redirect URI with an additional code parameter: <redirect_uri>?code=<code parameter>
, for example: https://example.com/?code=AbCdEf
.
- Use this code to get the access token and refresh token. To do this, make an HTTP
POST
request to "https://auth.eagleeyenetworks.com/oauth2/token" with the following parameters:
grant_type
: "authorization_code"scope
: "vms.all"code
: The code parameter from the previous stepredirect_uri
: The redirect URI with http(s)://
You must authenticate the request with your 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. In addition, the code must be used within 5 minutes of being generated or it will expire.
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/json
header to the HTTPPOST
request.- The
content-type
header 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.
In response, you'll recieve an access token and a refresh token. The access token has a miaximum lifespan of 12 hours and can be used to authenticate API calls. 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"
}
Result: You obtained the access token and Base URL. The returned access token can be used for accessing the user data. For example, to get a camera overview or recording.
Phase 2: Machine-to-machine (M2M) authentication
M2M Authentication with an Expiring Refresh Token
Once the refresh token is obtained, it can be used for logging in again. The refresh token replaces the username and password. Instead of storing username and password combinations, the database stores the refresh tokens. This way the customer's password is never stored anywhere or could be exposed.
Important
It 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 Rotation
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.
Token Life Cycle
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 steps in Phase 1 of this guide.
M2M authentication using Non-Rotating Refresh Tokens
While we highly recommend to architect 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 expriration time of the access token will not be changed.
No Forced Rotation
Unlike 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 recomended 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 16 days ago