- Implemented OAuth2 server with client registration, authorization, and token endpoints. - Created HTML templates for client authorization, client creation, and client editing. - Developed an OAuth2 client application using Hono.js and Bun, supporting authorization code grant flow. - Integrated PKCE (Proof Key for Code Exchange) for enhanced security during authorization. - Added session management using cookies for user authentication. - Included detailed README documentation for setup and usage instructions.
120 lines
5.1 KiB
HTML
120 lines
5.1 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>OAuth Client 수정</title>
|
|
<style>
|
|
body { font-family: Arial, sans-serif; margin: 40px; }
|
|
.form-group { margin-bottom: 15px; }
|
|
label { display: block; margin-bottom: 5px; font-weight: bold; }
|
|
input[type="text"], input[type="url"], textarea, select {
|
|
width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px;
|
|
}
|
|
textarea { height: 60px; resize: vertical; }
|
|
button {
|
|
background-color: #007bff; color: white; padding: 10px 20px;
|
|
border: none; border-radius: 4px; cursor: pointer; margin-right: 10px;
|
|
}
|
|
button:hover { background-color: #0056b3; }
|
|
.danger { background-color: #dc3545; }
|
|
.danger:hover { background-color: #c82333; }
|
|
.client-info {
|
|
background-color: #f8f9fa; padding: 15px; margin-bottom: 20px;
|
|
border-radius: 4px; border: 1px solid #dee2e6;
|
|
}
|
|
.checkbox-group { display: flex; align-items: center; }
|
|
.checkbox-group input[type="checkbox"] { width: auto; margin-right: 10px; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>OAuth Client 수정</h1>
|
|
|
|
<div class="client-info">
|
|
<h3>현재 클라이언트 정보</h3>
|
|
<p><strong>Client ID:</strong> {{ client.client_id }}</p>
|
|
<p><strong>Client Secret:</strong>
|
|
{% if client.client_secret %}
|
|
{{ client.client_secret[:8] }}...
|
|
{% else %}
|
|
(없음 - Public Client)
|
|
{% endif %}
|
|
</p>
|
|
<p><strong>생성일:</strong> {{ client.client_id_issued_at }}</p>
|
|
</div>
|
|
|
|
<form method="post">
|
|
<div class="form-group">
|
|
<label for="client_name">클라이언트 이름:</label>
|
|
<input type="text" id="client_name" name="client_name"
|
|
value="{{ client.client_metadata.get('client_name', '') }}" required>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="client_uri">클라이언트 URI:</label>
|
|
<input type="url" id="client_uri" name="client_uri"
|
|
value="{{ client.client_metadata.get('client_uri', '') }}">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="redirect_uri">Redirect URIs (각 줄에 하나씩):</label>
|
|
<textarea id="redirect_uri" name="redirect_uri" required>{% for uri in client.client_metadata.get('redirect_uris', []) %}{{ uri }}
|
|
{% endfor %}</textarea>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="scope">Scope:</label>
|
|
<input type="text" id="scope" name="scope"
|
|
value="{{ client.client_metadata.get('scope', '') }}">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="grant_type">Grant Types (각 줄에 하나씩):</label>
|
|
<textarea id="grant_type" name="grant_type" required>{% for grant in client.client_metadata.get('grant_types', []) %}{{ grant }}
|
|
{% endfor %}</textarea>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="response_type">Response Types (각 줄에 하나씩):</label>
|
|
<textarea id="response_type" name="response_type" required>{% for response in client.client_metadata.get('response_types', []) %}{{ response }}
|
|
{% endfor %}</textarea>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="token_endpoint_auth_method">Token Endpoint Auth Method:</label>
|
|
<select id="token_endpoint_auth_method" name="token_endpoint_auth_method" required>
|
|
<option value="client_secret_basic"
|
|
{% if client.client_metadata.get('token_endpoint_auth_method') == 'client_secret_basic' %}selected{% endif %}>
|
|
client_secret_basic
|
|
</option>
|
|
<option value="client_secret_post"
|
|
{% if client.client_metadata.get('token_endpoint_auth_method') == 'client_secret_post' %}selected{% endif %}>
|
|
client_secret_post
|
|
</option>
|
|
<option value="none"
|
|
{% if client.client_metadata.get('token_endpoint_auth_method') == 'none' %}selected{% endif %}>
|
|
none
|
|
</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<div class="checkbox-group">
|
|
<input type="checkbox" id="regenerate_secret" name="regenerate_secret">
|
|
<label for="regenerate_secret">Client Secret 재생성 (기존 토큰들이 무효화됩니다)</label>
|
|
</div>
|
|
</div>
|
|
|
|
<button type="submit">클라이언트 수정</button>
|
|
<a href="/" style="text-decoration: none;">
|
|
<button type="button">취소</button>
|
|
</a>
|
|
</form>
|
|
|
|
<hr style="margin: 30px 0;">
|
|
|
|
<h3>위험 영역</h3>
|
|
<form method="post" action="{{ url_for('.delete_client', client_id=client.id) }}"
|
|
onsubmit="return confirm('정말로 이 클라이언트를 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다.')">
|
|
<button type="submit" class="danger">클라이언트 삭제</button>
|
|
</form>
|
|
</body>
|
|
</html>
|