8

I'm new at IdentityServer4. I read I need to implement an IPersistedGrantStore to store refresh tokens into a table like PersistedGrants in my database.

IdentityServer logs is the following when my native app ask for a new access token: "refresh_token" grant with value: "{value}" not found in store.

That's because I'm using in-memory version of the persisted grant store. So I need to store refresh token in a PersistedGrant table.

Therefore in my startup.cs I added the following line:

builder.Services.AddScoped<IPersistedGrantStore, PersistedGrantStore>();

and IPersistedGrantStore.cs is

public interface IPersistedGrantStore
{        
    Task StoreAsync(CustomPersistedGrant grant);

    Task<CustomPersistedGrant> GetAsync(string key);

    Task<IEnumerable<CustomPersistedGrant>> GetAllAsync(string subjectId);        
}

So I have a CustomPersistedGrant.cs class

public class CustomPersistedGrant
{
    public string Key { get; set; }

    public string Type { get; set; }

    public string SubjectId { get; set; }

    public string ClientId { get; set; }

    public DateTime CreationTime { get; set; }

    public DateTime? Expiration { get; set; }

    public string Data { get; set; }
}

and now I have to write the code for my PersistedGrantStore.cs class. But the question is: once I have write code for PersistedGrantStore.cs class where I call PersistedGrantStore.cs class? In Identity.Server Account/AccountController? I didn't find any example about it without use EntityFramework, because I don't want to use Entity Framework.

Thanks.

Mini Dev 1
  • 169
  • 1
  • 2
  • 8

2 Answers2

6

The key will be to implement IPersistedGrantStore using whatever backend you like, then to tell IdentityServer to use that implementation by registering the implementation in the dependency injection system.

For example, if you call your implementation PersistedGrantStore, then you could register the implementation like this:

services.AddTransient<IPersistedGrantStore, PersistedGrantStore>();

You can see that essentially this is all that the EntityFramework implementation does, once you take away all the EntityFramework stuff.

Later when IdentityServer wants to persist a grant, it will get your implementation and call the appropriate method. So you don't have to do anything, other than inject your implementation into IdentityServer so it can do whats needed.

Jim Counts
  • 12,535
  • 9
  • 45
  • 63
  • 2
    Thanks. In my **startup.cs** I've registered the implementation with this line: `builder.Services.AddScoped();` . My goal is to persist a grant, but where's the code to persist a grant using `IPersistedGrantStore` and my `PersistedGrantStore` in IdentityServer4. I don't found any reference in QuickStartIdentityServer project on github – Mini Dev 1 Nov 16 '17 at 08:25
  • That is an IdentityServer internal call. You don't need to call the PersistedGrant store, just like you don't need to make the call when using the InMemory version. – Jim Counts Nov 16 '17 at 20:18
  • In my `PersistedGrantStore` I implemented all interfaces member and I put a breakpoint at the beginning of every method in this class to debug. The problem is that the application doesn't break but I don't understand where I'm doing wrong. I configure my client with `GrantTypes.Code`, `RequireConsent = false`, `AllowOfflineAccess = true`. Am I missing something? – Mini Dev 1 Dec 08 '17 at 09:18
  • Hi @Jim, I tried several times, using an extension helper class like in [this project](https://github.com/IdentityServer/IdentityServer4.EntityFramework/blob/57b73e081ab87df02e95a323630ad00169aa0f5c/src/IdentityServer4.EntityFramework/Extensions/IdentityServerEntityFrameworkBuilderExtensions.cs#L138) or writing directly `services.AddTransient();` in **startup.cs** but the first line of log is always `You are using the in-memory version of the persisted grant store`. Where am I mistaking? – Mini Dev 1 Jan 04 '18 at 15:13
  • HI @MiniDev1, Did you find the solution for this? I am also getting same kind of issue. – Jaydeep Jadav Jun 12 '19 at 07:06
  • Hi @JaydeepJadav, yes you have to use interface of IdentityServer not your own interface – Mini Dev 1 Jun 12 '19 at 07:41
  • @MiniDev1: I used `IdentityServer4.Stores.IPersistedGrantStore` and implemented all methods. I also registered the strore in Startup.cs using `AddPersistedGrantStore()` But still no luck. Also I am not getting any kind of error message like `You are using the in-memory version of the persisted grant store` but none of the method of `CustomPersistedGrantStore` is getting hit. Any idea of these? – Jaydeep Jadav Jun 12 '19 at 08:07
  • I am using GrantTypes = ClientCredentials – Jaydeep Jadav Jun 12 '19 at 08:09
  • 1
    With client credentials you don't need to persist authorization code, refresh tokens or stroing consent – Mini Dev 1 Jun 12 '19 at 08:35
  • Yes, I understand. Thanks for sharing the detailed link – Jaydeep Jadav Jun 26 '19 at 12:37
3

I know the question is kind of old and you might have already found the problem. I think your only mistake is that you invented your own interface instead of implementing:

IdentityServer4.Stores.IPersistedGrantStore

If you want to use your own CustomPersistedGrant it should derive from:

IdentityServer4.Models.PersistedGrant

otherwise you would have to wrap it somehow.

Mithrandir
  • 131
  • 7