Genius DM

IdentityServer > Storing an access token in IdentityServer3 본문

.NET

IdentityServer > Storing an access token in IdentityServer3

Damon Jung 2018. 7. 8. 16:01

IdentityServer3 토큰 데이터베이스에 저장하기


IdentityServer3 웹 어플리케이션이나 OAuth2, OpenID Connect 등의 프로토콜을 사용하는 API 에 대한 접근 제어 & SSO 를 이식하는 데 유용한 프레임워크이자 호스팅 가능한 컴퍼넌트이다. 다양한 어플리케이션을 지원하여 범용적으로 활용할 수 있다. Documentation 은 상대적으로 미비하나, Example 소스코드 제공은 매우 풍부하게 되어있는 편이다. 샘플 레파지터리는 https://github.com/IdentityServer/IdentityServer3.Samples/ 이곳에서 다운받을 수 있다.



ITokenHandleStore, ITransientDataRepository<Token>

Token 을 데이터베이스에 저장하기 위해서는 ITokenHandleStore 인터페이스가 필요하다. ITokenHandleStore Signature 는 비어 있다. 


해당 Interface 는 ITransientDataRepository<T> 를 상속하므로, 해당 인터페이스의 Signature 를 구현해야 한다.



Interface Signature 만 보더라도, 어떤 행위를 하는 지 짐작할 수 있다.


    • GetAllAsync : 모든 Token 리스트를 반환
    • GetAsync : key 로 매칭되는 싱글 Token 을 만환
    • RemoveAsync : key 로 매칭되는 Token 삭제
    • RevokeAsync : subject 와 client 에 매칭되는 Token 삭제 ( 정확히 말하면 철회 개념이지만, 어쨌든 Token 을 삭제하는 로직이다. )
    • StoreAsync : key 와 value 를 저장.

이 Interface 를 구현하는 것이 정확한 작업의 방향일까? 




Interface 관계에 대한 Diagram 인데, InMemoryTokenHandleStore 가 ITokenHandleStore 를 구현한 클래스라는 것을 바로 알 수 있다. IdentityServer3 Default Sample 대부분은 인메모리 기능을 사용하므로, 거의 확실하다고 볼 수 있다. 그럼 작업을 진행해보자.



구현

바로 코드를 통한 Sample 을 보자. 
* Sudo 코드이므로, Application 환경에 맞춰서 DbContext 를 작성하면 된다. ADO.NET 이면 SqlConnection 을 명시적으로 선언하여 사용하거나, EntityFramework 를 사용한다면 Token 모델을 이용해서 쿼리 작성할 필요 없이 ORM 방식으로 작성하면 된다.



구성

이제 직접 작성한 구현 ( GeniusDMTokenHandleStore ) 을 IdentityServer 에서 사용할 수 있도록 Factory 에 등록을 해주어야 한다. 프로젝트마다 다르지만, 보통 WebHost 프로젝트의 Startup.cs 에서 아래와 같은 구문을 찾을 수 있을 것이다.



이 ServiceFactory 를 통해서 GeniusDMTokenHandleStore 를 등록하면, IdentityServer3 에서 Autofac 을 이용하여 DI ( Dependency Injection ) 을 수행하게 된다. "TokenHandleStore" 를 구현했으므로, Factory 에 이미 존재하는 해당 Property 에 아래와 같이 Registration 처리를 하도록 하자.



이제 정상적인 Client 와 Scope 를 이용해서 localhost:{yourport}/connect/token 을 통해 Token 발급을 시도하면, GeniusDMTokenHandleStore 에서 작성한 처리를 AccessTokenValidation 과정에서 수행하는 것을 볼 수 있을 것이다. 만약 Factory Registration 과정에서 DI 행위시 생성자에 특정 파라메터를 넘기고 싶다면, 아래와 같이 생성자를 지정할 수도 있다. 이를 통해서 IoC 컨테이너가 해당 클래스를 초기화 할 때, 원하는 생성자를 호출하도록 행위를 지정하는 것이다.









Storing an access token in IdentityServer3


IdentityServer is a framework and a hostable component that allows implementing single sign-on and access control for modern web applications and APIs using protocols like OpenID Connect and OAuth2. The documentation is not so great, but the example source codes are very well supported. You can find the codes here in https://github.com/IdentityServer/IdentityServer3.Samples/



ITokenHandleStore, ITransientDataRepository<Token>

In order to save the token in your own database, the first thing you should dig into is ITokenHandleStore interface. As you can see below, the signature is empty.


This interface inherits ITransientDataRepositry<T>, you need to implement its signature.



You can get these from just taking a glance at the signature.


  • GetAllAsync : Get all the tokens.
  • GetAsync : Get a token matched by the key parameter
  • RemoveAsync : Remove a token matched by the key parameter
  • RevokeAsync : Remove a token or bunch of tokens matched by subject and client parameter ( they are subject id and client id respectively )
  • StoreAsync : Save an access key with token model.

Is it a right choice or a right approach to implement ITokenHandleStore interface? 




It's a diagram that shows a hierarchical relationships between the interface and its implementations. You can see the InMemoryTokenHandleStore directly inherits ITokenHandleStore. Well it depends on the project and configuration, the majority of examples use InMemoryTokenHandleStore as a default, we can be pretty much sure that this is the right one. Let's tweak some codes.



Implementation

Let's see the codes below. 
* this is just sudo codes. You need to write your own DbContext according to your application environment. If you use plain ADO.NET, then write SqlConnection codes explicitly or if you use EntityFramework, then all you need to do is to write queries with the Token model in ORM way.


Configuration

Now it's essential to register your own service ( GeniusDMTokenHandleStore ) into the Factory. It does also depend on your project, normally you can find these statements in your Startup.cs in your WebHost project.



Once you successfully registered your own implementation via ServiceFactory, then Autofac in IdentityServer3 will do the heavy liftings for you. It's going to perform DI ( Dependency Injection ) for you. For Autofac to do this job properly, let's register your class.



It's all set. From now on, let's make a http request to localhost:{yourport}/connect/token with a proper client and scopes. When IdentityServer3 tries to validate your token, it will try to get the token through your implementation. If you want to pass in something that you need for your database ( eg. ConnectionString ), you may need to add a constructor to your implementation, so that Autofac, the IoC container will be able to instantiate your class just like the way you wanted. See this example below.































Comments