mirror of
https://github.com/Eugeny/tabby-web.git
synced 2026-08-17 06:46:05 +01:00
feat: dynamic auth providers + Auth0 support
- Add /api/1/auth/providers endpoint that returns only configured providers - Frontend fetches available providers dynamically instead of hardcoding - Only providers with credentials set (KEY + SECRET) appear as login options - Add Auth0 as a supported authentication provider - Add python-jose[cryptography] dependency for Auth0 JWT verification - Show helpful message when no providers are configured This makes the login page modular - administrators only see buttons for providers they've actually configured, avoiding confusion from dead buttons. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
.login-view(*ngIf='ready')
|
||||
.buttons
|
||||
.buttons(*ngIf='providers.length')
|
||||
a.btn(
|
||||
*ngFor='let provider of providers',
|
||||
[class]='provider.cls',
|
||||
href='{{commonService.backendURL}}/api/1/auth/social/login/{{provider.id}}'
|
||||
)
|
||||
fa-icon([icon]='provider.icon', [fixedWidth]='true')
|
||||
fa-icon([icon]='provider.faIcon', [fixedWidth]='true')
|
||||
span Log in with {{provider.name}}
|
||||
.no-providers(*ngIf='!providers.length')
|
||||
p No authentication providers configured.
|
||||
p.text-muted Contact your administrator.
|
||||
|
||||
@@ -23,3 +23,12 @@
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.no-providers {
|
||||
text-align: center;
|
||||
color: #6c757d;
|
||||
|
||||
p {
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,25 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { HttpClient } from '@angular/common/http'
|
||||
import { LoginService, CommonService } from 'src/common'
|
||||
|
||||
import { faGithub, faGitlab, faGoogle, faMicrosoft } from '@fortawesome/free-brands-svg-icons'
|
||||
import { faGithub, faGitlab, faGoogle, faMicrosoft, IconDefinition } from '@fortawesome/free-brands-svg-icons'
|
||||
import { faKey } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
interface Provider {
|
||||
id: string
|
||||
name: string
|
||||
icon: string
|
||||
cls: string
|
||||
}
|
||||
|
||||
// Map icon names from backend to FontAwesome icons
|
||||
const iconMap: Record<string, IconDefinition> = {
|
||||
github: faGithub,
|
||||
gitlab: faGitlab,
|
||||
google: faGoogle,
|
||||
microsoft: faMicrosoft,
|
||||
key: faKey, // Used for Auth0 and other providers without brand icons
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'login',
|
||||
@@ -11,20 +29,27 @@ import { faGithub, faGitlab, faGoogle, faMicrosoft } from '@fortawesome/free-bra
|
||||
export class LoginComponent {
|
||||
loggedIn: any
|
||||
ready = false
|
||||
|
||||
providers = [
|
||||
{ name: 'GitHub', icon: faGithub, cls: 'btn-primary', id: 'github' },
|
||||
{ name: 'GitLab', icon: faGitlab, cls: 'btn-warning', id: 'gitlab' },
|
||||
{ name: 'Google', icon: faGoogle, cls: 'btn-secondary', id: 'google-oauth2' },
|
||||
{ name: 'Microsoft', icon: faMicrosoft, cls: 'btn-light', id: 'microsoft-graph' },
|
||||
]
|
||||
providers: Array<Provider & { faIcon: IconDefinition }> = []
|
||||
|
||||
constructor (
|
||||
private http: HttpClient,
|
||||
private loginService: LoginService,
|
||||
public commonService: CommonService,
|
||||
) { }
|
||||
|
||||
async ngOnInit () {
|
||||
// Fetch available providers from backend
|
||||
try {
|
||||
const providers = await this.http.get<Provider[]>('/api/1/auth/providers').toPromise()
|
||||
this.providers = (providers || []).map(p => ({
|
||||
...p,
|
||||
faIcon: iconMap[p.icon] || faKey,
|
||||
}))
|
||||
} catch {
|
||||
// Fallback to empty list if API fails
|
||||
this.providers = []
|
||||
}
|
||||
|
||||
await this.loginService.ready$.toPromise()
|
||||
this.loggedIn = !!this.loginService.user
|
||||
this.ready = true
|
||||
|
||||
Reference in New Issue
Block a user