cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
6110
Views
15
Helpful
10
Replies

DNAC 1.1 API Authertication discusion

daxu2
Cisco Employee
Cisco Employee

Hello expert:

   from dnac api 1.1 version,it change the authertication model.

   APIC-EM API authertication step

  1) send get login request and get a token.

  2) all other api want be invoked must using token

  3) close the session

  but now DNAC api

   1) send get login request,but no token returned

   2) call other api,not need token

I do the follow testing

  1) i do not send login request,and direct to call get network device,it also work good.

so i think now DNAC API login is not needed,it is so danger.

1 Accepted Solution

Accepted Solutions

jafrazie
Cisco Employee
Cisco Employee

Hi Da:

There are 3 APIs here you might need:

  1. api/system/v1/auth/login — this logs in and DNAC will return a cookie. Most web clients (like Paw or Postman) store cookies set by servers in a Cookie session and automatically send them back in subsequent requests. You should be able to optionally disable this if on a per-request basis for the client in question. The cookie’s idle-timeout is 30min. Thus, if you make no subsequent request for 30min, you will need to login again.
  2. api/system/v1/auth/logoff — this logs you out directly, and clears state.
  3. api/system/v1/auth/token — this returns a token as a response in a JSON object. This way, you can re-use it for any request that may need it directly (Python script, Ansible, etc.).

Hope this helps,

View solution in original post

10 Replies 10

yawming
Cisco Employee
Cisco Employee

Can you please share the detail steps of doing DNAC request in your way?

jafrazie
Cisco Employee
Cisco Employee

Hi Da:

There are 3 APIs here you might need:

  1. api/system/v1/auth/login — this logs in and DNAC will return a cookie. Most web clients (like Paw or Postman) store cookies set by servers in a Cookie session and automatically send them back in subsequent requests. You should be able to optionally disable this if on a per-request basis for the client in question. The cookie’s idle-timeout is 30min. Thus, if you make no subsequent request for 30min, you will need to login again.
  2. api/system/v1/auth/logoff — this logs you out directly, and clears state.
  3. api/system/v1/auth/token — this returns a token as a response in a JSON object. This way, you can re-use it for any request that may need it directly (Python script, Ansible, etc.).

Hope this helps,

To convert from APIC-EM to DNA-C you just need to choose option #3 as provided by Jason.

Note that the JSON body will have changed too.

It will contain a single key called "Token".

You no longer see the active/idle timeout in the token request either.

APIC-EM session control mechanism is clear, when login ,we will get a ticket,using this ticket as indentify to invoke other API. close the ticket,the session is close.


but I do not know  what the session management mechanism in DNAC,it only have an login api,but other session control is no idea.

nefkensp
Level 5
Level 5

It is correct that you first need to authenticate yourself via

"api/system/v1/auth/login"

The authentication is just an Authorization header with the text Basic<space>base64(<username>:<password>)

But be aware if you do not use postman or some other test-tool, but write your own code.

The cookie returned from the DNA-C sandbox has an empty domain, which is not according to RFC. As a result, some libraries do not accept the cookie and you cannot continue.

I created my own DNA-C cookie handler to put the domain-value of the URL into the cookie if the domain attribute is empty.

It took me some debugging time to find this out. But now I can get the required data.

Hope this helps others along

PS: Also the authentication API doesn't respond with JSON formatted code,but just the string "success".

Hi Pj:

I see a domain coming back from sandboxdnac.cisco.com. Are you seeing it?

Also, yes; we have a bug filed on the JSON string coming back.

Fixed up in the 1.2 release forthcoming.

Great to see the login begin fixed in 1.2.

With regards to the cookie and domain, if you use postman and look at the headers, this is wat is being sent back:

Set-Cookie →X-JWT-ACCESS-TOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI1YTU4Y2QzN2UwNWJiYTAwOGVmNjJiOTIiLCJhdXRoU291cmNlIjoiaW50ZXJuYWwiLCJ0ZW5hbnROYW1lIjoiVE5UMCIsInJvbGVzIjpbIjVhMzE1MTYwOTA5MGZiYTY5OGIyZjViNyJdLCJ0ZW5hbnRJZCI6IjVhMzE1MTlkZTA1YmJhMDA4ZWY2MWYwYSIsImV4cCI6MTUyMTgyMDE3NywidXNlcm5hbWUiOiJkZXZuZXR1c2VyIn0.Qw2OoerVo8O_82RUA72NCfUlfNZTXrcIK7E54zkPvAg;Version=1;Comment=;Domain=;Path=/;Max-Age=3600;Secure;HttpOnly

And as you can see, the Domain value is empty, so Postman will fill that for you. however, if you use the apache http client (I'm using the Unirest Client from Kong within Java), it will throw an exception because the cookie is invalid.

So I had to rewrite some code to get that cookie accepted and being used.. It didn't matter which Cookie parser I used.

So my assumption is that postmap accepts the cookie and completes it with the hostname it was connecting to.

I don't see the domain name either. But in my case (using Python requests) I can use cookie in different places for subsequent request.

1.place in header:

rawcookies = resp.headers['Set-Cookie']

print(rawcookies)

X-JWT-ACCESS-TOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI1YTU4Y2QzN2UwNWJiYTAwOGVmNjJiOTIiLCJhdXRoU291cmNlIjoiaW50ZXJuYWwiLCJ0ZW5hbnROYW1lIjoiVE5UMCIsInJvbGVzIjpbIjVhMzE1MTYwOTA5MGZiYTY5OGIyZjViNyJdLCJ0ZW5hbnRJZCI6IjVhMzE1MTlkZTA1YmJhMDA4ZWY2MWYwYSIsImV4cCI6MTUyMTgyNTI3NCwidXNlcm5hbWUiOiJkZXZuZXR1c2VyIn0._8vsXLFRSbVr7zPGgIAd6zdvcwp5eZplN41wfKfktbE;Version=1;Comment=;Domain=;Path=/;Max-Age=3600;Secure;HttpOnly

resp = s.get(url,headers=headers,verify=False)

2. using cookies parameter :

cookie = SimpleCookie()

cookie.load(rawcookies)

# used in request cookies=cookies

cookies = {}

for key, morsel in cookie.items():

    cookies[key] = morsel.value


print (cookies)

{'X-JWT-ACCESS-TOKEN': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI1YTU4Y2QzN2UwNWJiYTAwOGVmNjJiOTIiLCJhdXRoU291cmNlIjoiaW50ZXJuYWwiLCJ0ZW5hbnROYW1lIjoiVE5UMCIsInJvbGVzIjpbIjVhMzE1MTYwOTA5MGZiYTY5OGIyZjViNyJdLCJ0ZW5hbnRJZCI6IjVhMzE1MTlkZTA1YmJhMDA4ZWY2MWYwYSIsImV4cCI6MTUyMTgyNTI3NCwidXNlcm5hbWUiOiJkZXZuZXR1c2VyIn0._8vsXLFRSbVr7zPGgIAd6zdvcwp5eZplN41wfKfktbE'}

resp = s.get(url,cookies=cookies,verify=False)


Either way works fine.



I got it working as well, by overriding the cookie parser in the HTTP client.

I guess it depends on the strictness of the HTTP client (or REST cliend) being used for the communication.

I'm going to write a blog about it in the near future..

Is there a reason you do not want to use the /token API call?

that is supported (and will be added to documentation soon).

It is much simpler as the token is just a JSON response

POST /api/system/v1/auth/token - with BASIC AUTH

returns

{

    "Token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI1YTIwMjExY2I2MjZjOTAwOGUzMDc1NjMiLCJhdXRoU291cmNlIjoiaW50ZXJuYWwiLC-XXXXXXX"

}