Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSO: Add redirect_uri to oAuth auth request #969

Merged
merged 3 commits into from
Dec 7, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 20 additions & 9 deletions components/connection/ServerConnectForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export default {
processing: false,
serverConfig: {
address: null,
version: null,
username: null,
customHeaders: null
},
Expand All @@ -107,7 +108,8 @@ export default {
state: null,
verifier: null,
challenge: null,
buttonText: 'Login with OpenID'
buttonText: 'Login with OpenID',
enforceHTTPs: true // RFC 6749, Section 10.9 requires https
}
}
},
Expand Down Expand Up @@ -155,7 +157,7 @@ export default {
*/
async clickLoginWithOpenId() {
// oauth standard requires https explicitly
if (!this.serverConfig.address.startsWith('https')) {
if (!this.serverConfig.address.startsWith('https') && this.oauth.enforceHTTPs) {
console.warn(`[SSO] Oauth2 requires HTTPS`)
this.$toast.error(`SSO: The URL to the server must be https:// secured`)
return
Expand All @@ -179,14 +181,19 @@ export default {
const client_id = redirectUrl.searchParams.get('client_id')
const scope = redirectUrl.searchParams.get('scope')
const state = redirectUrl.searchParams.get('state')
let redirect_uri_param = redirectUrl.searchParams.get('redirect_uri')
// Backwards compatability with 2.6.0
if (this.serverConfig.version === '2.6.0') {
redirect_uri_param = 'audiobookshelf://oauth'
}

if (!client_id || !scope || !state) {
console.warn(`[SSO] Invalid OpenID URL - client_id scope or state missing: ${redirectUrl}`)
if (!client_id || !scope || !state || !redirect_uri_param) {
console.warn(`[SSO] Invalid OpenID URL - client_id scope state or redirect_uri missing: ${redirectUrl}`)
this.$toast.error(`SSO: Invalid answer`)
return
}

if (redirectUrl.protocol !== 'https:') {
if (redirectUrl.protocol !== 'https:' && this.oauth.enforceHTTPs) {
console.warn(`[SSO] Insecure Redirection by SSO provider: ${redirectUrl.protocol} is not allowed. Use HTTPS`)
this.$toast.error(`SSO: The SSO provider must return a HTTPS secured URL`)
return
Expand All @@ -195,8 +202,8 @@ export default {
// We need to verify if the state is the same later
this.oauth.state = state

const host = `https://${redirectUrl.host}`
const buildUrl = `${host}${redirectUrl.pathname}?response_type=code` + `&client_id=${encodeURIComponent(client_id)}&scope=${encodeURIComponent(scope)}&state=${encodeURIComponent(state)}` + `&redirect_uri=${encodeURIComponent('audiobookshelf://oauth')}` + `&code_challenge=${encodeURIComponent(this.oauth.challenge)}&code_challenge_method=S256`
const host = `${redirectUrl.protocol}//${redirectUrl.host}`
const buildUrl = `${host}${redirectUrl.pathname}?response_type=code` + `&client_id=${encodeURIComponent(client_id)}&scope=${encodeURIComponent(scope)}&state=${encodeURIComponent(state)}` + `&redirect_uri=${encodeURIComponent(redirect_uri_param)}` + `&code_challenge=${encodeURIComponent(this.oauth.challenge)}&code_challenge_method=S256`

// example url for authentik
// const authURL = "https://authentik/application/o/authorize/?response_type=code&client_id=41cd96f...&redirect_uri=audiobookshelf%3A%2F%2Foauth&scope=openid%20openid%20email%20profile&state=asdds..."
Expand Down Expand Up @@ -243,8 +250,11 @@ export default {
this.oauth.verifier = verifier
this.oauth.challenge = challenge

// set parameter isRest to true, so the backend wont attempt a redirect after we call backend:/callback in exchangeCodeForToken
const backendEndpoint = `${url}/auth/openid?code_challenge=${challenge}&code_challenge_method=S256&isRest=true`
let backendEndpoint = `${url}/auth/openid?code_challenge=${challenge}&code_challenge_method=S256&redirect_uri=${encodeURIComponent('audiobookshelf://oauth')}&client_id=${encodeURIComponent('Audiobookshelf-App')}&response_type=code`
// Backwards compatability with 2.6.0
if (this.serverConfig.version === '2.6.0') {
backendEndpoint += '&isRest=true'
}

try {
const response = await CapacitorHttp.get({
Expand Down Expand Up @@ -608,6 +618,7 @@ export default {
this.showAuth = true
this.authMethods = statusData.data.authMethods || []
this.oauth.buttonText = statusData.data.authFormData?.authOpenIDButtonText || 'Login with OpenID'
this.serverConfig.version = statusData.data.serverVersion

if (statusData.data.authFormData?.authOpenIDAutoLaunch) {
this.clickLoginWithOpenId()
Expand Down