Azure-Samples / active-directory-dotnet-graphapi-web

A .NET 4.5 MVC web app that demonstrates how to query the Azure AD Graph API using the Azure AD Graph Client Library
82 stars 68 forks source link

Can I drop the token cache? #14

Closed guardrex closed 9 years ago

guardrex commented 9 years ago

It looks like the token cache is running on session state. Can you provide some guidance for using the API with stateless apps (specifically when the session state mode is set to "Off" in Web.config)? I only need one-time access to AD for populating my app's membership; therefore, I don't need to cache tokens.

Can't I remove the statement for obtaining a NaiveSessionCache and take an AuthenticationContext with the method that only requires the authority parameter? I understand that if I need to perform any other Graph API work, I'll need to get a new token.

What about doing this when the request returns with a Request.QueryString["reauth"] == "True" and I need to send an OpenID Connect sign-in request to get a new set of tokens? Will having the session state (and the token cache) disabled cause a problem with that process?

vibronet commented 9 years ago

Hi, the challenge here is that the token is obtained by a single use authorization code, which is processed when the first authentication takes place. The resulting token is placed in the cache, which is why the current code must work against the same cache in order to use the token in your own controllers when you want to actually call the service. If your code is truly one-shot, you could retrieve the access token as obtained in startup.auth.cs and make it available to your controllers using any other system. In that case, you don’t need to call acquiretokensilent from the controller. However I would discourage you to do so, given that it would trigger auth prompts far more often than necessary or would force you to re-implement complicated logic about deling with refresh tokens that you get for free when you use the cache as shown in the sample. HTH

JonPSmith commented 9 years ago

hi @GuardRex. I don't know if it helps but I have been looking a lot at the WebApp-GroupClaims-DotNet sample and that, to me, has better commented code around the use of GraphApi. I felt I understood the token part of GraphApi ver 2 much better from this sample than on the WebApp-GraphAPI-DotNet sample. It uses a database to hold the token, which is scalable.

One minor note: For some strange reason they removed the code walkthrough from the README file from WebApp-GroupClaims-DotNet. I find that odd as I found the code walkthrough really useful to get an overview, and it includes talking about how the token is used. Here is a link to the original version with README in case you find that useful too.

guardrex commented 9 years ago

Vittorio, Jon,

Thanks for the info and tips. As far as the Graph API helper class goes (NativeSessionCache.cs), I feel confident that I can simply store and retrieve the Graph API tokens by modifying the code in that helper class (e.g., use Azure dedicated caching to keep the tokens without ever needing to add a .NET session state provider to the app) ... but that's only a utility class for the Graph API, correct? Vittorio, you're hinting that the ADAL has .NET sessions baked into it's library, right? Therefore, I can't simply modify a few calls to the .NET session state as I can with the Graph API helper class.

If I'm right about that, then I think you are about to suggest that I setup an out-of-process session state provider for the app, such as SQL Server, Azure Caching, etc. This app (as many that I work with) span multiple instances, and this one just happens to be stateless (but still requires a login against AAD).

Jon, thanks for that tip ... I was able to get Graph API working fine without the token cache running, because I only call it once on login to get membership data for the app. I'll take a look at the GroupClaims example you reference.

guardrex commented 9 years ago

It looks like the Group Claims example app is merely using application RAM to save its tokens, so it's even worse from a multi-instance standpoint. At least with the Graph API example, I can easily drop in an out-of-process session state provider and the utility helper class there will work unchanged (along with any session state calls that are baked into the ADAL API).

guardrex commented 9 years ago

And I'll just briefly add that there are some great tips in the Group Claims example for:

--> An additional signout step to clear the token cache:

string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
var authContext = new AuthenticationContext(ConfigHelper.Authority, new TokenDbCache(userObjectID));
authContext.TokenCache.Clear();

--> Additional handling for the redirect if the user should be sent back to a page that they weren't authorized to get when they first arrived:

if (redirectUri == null) redirectUri = "/";
HttpContext.GetOwinContext().Authentication.Challenge(new AuthenticationProperties {RedirectUri = redirectUri}, OpenIdConnectAuthenticationDefaults.AuthenticationType);
JonPSmith commented 9 years ago

Hi @GuardRex.

Glad your fixed on the token.

I don't suppose you need this but I was a bit puzzled when you said GroupClaims holds the token in memory. I did check and it holds the token in a database see TokenDbCache.

guardrex commented 9 years ago

My apologies ... you are correct.