Auth adjustments (#818)

Use the API interface instead of fetch() to make the HTTP HEAD
request to determine whether the SSE are protected.
Fix custom auth header logic.
Change probe endpoint to /rest/sitemaps.

Signed-off-by: Yannick Schaus <github@schaus.net>
pull/819/head
Yannick Schaus 2021-01-18 14:10:14 +01:00 committed by GitHub
parent 90f49f4d6b
commit cd659a794a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 27 additions and 22 deletions

View File

@ -41,7 +41,7 @@ export default {
this.$oh.api.postPlain('/rest/auth/token?useCookie=true', payload, 'application/json', 'application/x-www-form-urlencoded').then((data) => {
const resp = JSON.parse(data)
localStorage.setItem('openhab.ui:refreshToken', resp.refresh_token)
return this.$oh.auth.setAccessToken(resp.access_token).then(() => {
return this.$oh.auth.setAccessToken(resp.access_token, this.$oh.api).then(() => {
// schedule the next token refresh when 95% of this token's lifetime has elapsed, i.e. 3 minutes before a 1-hour token is due to expire
setTimeout(this.refreshAccessToken, resp.expires_in * 950)
this.$store.commit('setUser', { user: resp.user })
@ -73,7 +73,7 @@ export default {
this.$oh.auth.clearAccessToken()
this.$oh.api.postPlain('/rest/auth/token', payload, 'application/json', 'application/x-www-form-urlencoded').then((data) => {
const resp = JSON.parse(data)
return this.$oh.auth.setAccessToken(resp.access_token).then(() => {
return this.$oh.auth.setAccessToken(resp.access_token, this.$oh.api).then(() => {
// schedule the next token refresh when 95% of this token's lifetime has elapsed, i.e. 3 minutes before a 1-hour token is due to expire
setTimeout(this.refreshAccessToken, resp.expires_in * 950)
// also make sure to check the token and renew it when the app becomes visible again

View File

@ -12,7 +12,7 @@ function wrapPromise (f7promise) {
Framework7.request.setup({
xhrFields: { withCredentials: true },
beforeSend (xhr) {
if (getAccessToken()) {
if (getAccessToken() && xhr.requestParameters.method !== 'HEAD') {
if (getTokenInCustomHeader()) {
xhr.setRequestHeader('X-OPENHAB-TOKEN', getAccessToken())
} else {
@ -73,6 +73,12 @@ export default {
dataType: dataType || 'application/json'
}))
},
head (uri) {
return wrapPromise(Framework7.request.promise({
method: 'HEAD',
url: uri
}))
},
delete (uri, data) {
return wrapPromise(Framework7.request.promise({
method: 'DELETE',

View File

@ -18,14 +18,14 @@ let basicCredentials = null
/**
* The token is required for all requests, including SSE
*/
let requireToken = false
let requireToken
export function getAccessToken () { return accessToken }
export function getTokenInCustomHeader () { return tokenInCustomHeader }
export function getBasicCredentials () { return basicCredentials }
export function getRequireToken () { return requireToken }
if (document.cookie.indexOf('X-OPENHAB-AUTH-HEADER')) tokenInCustomHeader = true
if (document.cookie.indexOf('X-OPENHAB-AUTH-HEADER') >= 0) tokenInCustomHeader = true
export function authorize (setup) {
import('pkce-challenge').then((PkceChallenge) => {
@ -74,7 +74,7 @@ export function setBasicCredentials (username, password) {
export function clearBasicCredentials () {
basicCredentials = null
tokenInCustomHeader = document.cookie.indexOf('X-OPENHAB-AUTH-HEADER')
tokenInCustomHeader = document.cookie.indexOf('X-OPENHAB-AUTH-HEADER') >= 0
}
export function storeBasicCredentials () {
@ -83,23 +83,18 @@ export function storeBasicCredentials () {
}
}
export function setAccessToken (token) {
export function setAccessToken (token, api) {
accessToken = token
if (!token || !api || requireToken !== undefined) return
// determine whether the token is required for user operations
let headers = {}
if (getBasicCredentials()) {
const creds = getBasicCredentials()
headers.Authorization = 'Basic ' + btoa(creds.id + ':' + creds.password)
}
return fetch('rest/events', { method: 'HEAD', credentials: 'include', headers })
.then((resp) => {
if (resp.status === 401) {
requireToken = true
if (!token) authorize()
}
return Promise.resolve()
})
return api.head('/rest/sitemaps').then((resp) => {
requireToken = false
return Promise.resolve()
}).catch((err) => {
if (err === 'Unauthorized') requireToken = true
return Promise.resolve()
})
}
export function clearAccessToken () {

View File

@ -93,6 +93,10 @@ export default {
})
}
},
head (uri) {
// Not implemented
return Promise.resolve()
},
delete (uri, data) {
const fullUri = prepareRequest(uri)
if (fullUri) {

View File

@ -8,9 +8,9 @@ function newSSEConnection (path, readyCallback, messageCallback, errorCallback)
const headers = {}
if (getAccessToken() && getRequireToken()) {
if (getTokenInCustomHeader()) {
headers['Authorization'] = 'Bearer ' + getAccessToken()
} else {
headers['X-OPENHAB-TOKEN'] = getAccessToken()
} else {
headers['Authorization'] = 'Bearer ' + getAccessToken()
}
}
if (getBasicCredentials()) {