OpenID Connect
정의
- OIDC는 인증 및 인가를 위한 표준 프로토콜로, 클라이언트 애플리케이션과 인증 서버 간의 안전하고 효율적인 통신을 지원한다.
- OAuth 2.0 프로토콜 위에 구축되어 있다.
- 웹 및 모바일 애플리케이션에서 사용자를 인증하는 데 사용하여 사용자의 인증 및 인가 데이터를 안전하게 전송한다.
동작
- 클라이언트 애플리케이션(예: 웹 애플리케이션, 모바일 앱 등)과 인증 서버(예: Google, Facebook, Okta 등) 간의 상호 작용을 정의한다.
- 사용자는 클라이언트 애플리케이션을 통해 인증 서버에 로그인하고, 클라이언트 애플리케이션은 인증 서버로부터 인증된 사용자에 대한 정보를 안전하게 수신한다.
먼저, OAuth 클래스를 생성한다.
# for Starlette framework
from authlib.integrations.starlette_client import OAuth
oauth = OAuth()
첫째: 원격 애플리케이션을 oauth.register 메소드를 통해 OAuth 레지스트리에 등록한다.
oauth.register(
name='github', # 원격 애플리케이션의 이름
client_id='{{ your-github-client-id }}',
client_secret='{{ your-github-client-secret }}',
access_token_url='https://github.com/login/oauth/access_token',
access_token_params=None,
authorize_url='https://github.com/login/oauth/authorize',
authorize_params=None,
api_base_url='https://api.github.com/',
client_kwargs= {
'scope': 'profile',
},
)
원격 애플리케이션에 접근하는 방법:
github = oauth.create_client('github') # or github = oauth.github
OAuth 레지스트리 설정 후, 다음 두 개의 경로를 생성한다.
① 인증을 위해 서드파티 공급자(GitHub)로 리디렉션할 경로
② access token과 프로필을 가져오기 위해 재리디렉션할 경로
예시
def login(request):
github = oauth.create_client('github')
redirect_uri = 'https://example.com/authorize'
return github.authorize_redirect(request, redirect_uri)
def authorize(request):
token = oauth.github.authorize_access_token(request)
resp = oauth.github.get('user', token=token)
resp.raise_for_status()
profile = resp.json()
# do something with the token and profile
return '...'
access token을 가져올 때 권한 부여 서버는 클라이언트 인증을 요구하며, Authlib는 RFC7591에 정의된 세 가지 기본 방법을 제공한다.
그러나 원격 공급자가 위 방법을 모두 지원하지 않는 경우, 자체 인증 방법을 등록해야 한다.
from authlib.oauth2.rfc7523 import ClientSecretJWT
oauth.register(
'name',
...
client_auth_methods=[
ClientSecretJWT(token_endpoint), # client_secret_jwt
]
)
def get_twitter_tweets(request):
token = OAuth1Token.find(
name='twitter',
user=request.user
)
# API URL: https://api.twitter.com/1.1/statuses/user_timeline.json
resp = oauth.twitter.get('statuses/user_timeline.json', token=token.to_token())
resp.raise_for_status()
return resp.json()
def get_github_repositories(request):
token = OAuth2Token.find(
name='github',
user=request.user
)
# API URL: https://api.github.com/user/repos
resp = oauth.github.get('user/repos', token=token.to_token())
resp.raise_for_status()
return resp.json()
class OAuth2Token(Model):
name = String(length=40)
token_type = String(length=40)
access_token = String(length=200)
refresh_token = String(length=200)
expires_at = PositiveIntegerField()
user = ForeignKey(User)
def to_token(self):
return dict(
access_token=self.access_token,
token_type=self.token_type,
refresh_token=self.refresh_token,
expires_at=self.expires_at,
)
첫째: 개발자가 직접 토큰을 조회하는 방법
token = OAuth2Token.find(name='github', user=request.user)
oauth.github.get(url, token=token)
oauth.github.post(url, token=token)
oauth.github.put(url, token=token)
oauth.github.delete(url, token=token)
def fetch_twitter_token(request):
token = OAuth1Token.find(
name='twitter',
user=request.user
)
return token.to_token()
def fetch_github_token(request):
token = OAuth2Token.find(
name='github',
user=request.user
)
return token.to_token()
# we can registry this ``fetch_token`` with oauth.register
oauth.register(
'twitter',
# ...
fetch_token=fetch_twitter_token,
)
oauth.register(
'github',
# ...
fetch_token=fetch_github_token,
)
def fetch_token(name, request):
model = OAuth2Token
token = model.find(
name=name,
user=request.user
)
return token.to_token()
# 위 fetch_token 함수로 OAuth 레지스트리 초기화
oauth = OAuth(fetch_token=fetch_token)
def get_twitter_tweets(request):
resp = oauth.twitter.get('statuses/user_timeline.json', request=request)
resp.raise_for_status()
return resp.json()
OAuth 1.0은 프로토콜인 반면, OAuth 2.0은 프레임워크이다.
OAuth 2.0에서 토큰은 만료될 수 있는데, 만약 refresh_token 값이 존재한다면, Authlib은 **토큰이 만료된
경우 자동으로 갱신하는 기능**을 지원한다.
id_token은 JWT 형식으로, 이 토큰을 파싱하여 사용자의 정보를 확인할 수 있다.이와 같이 OAuth 및 OpenID Connect 인증 시스템을 설정하여 안전한 인증 흐름을 구현할 수 있다.