Merge pull request #1759 from mozilla/session-code-token

Add ability to attach a session token from the OAuth code flow
This commit is contained in:
Vlad Filippov 2019-09-16 15:42:11 -04:00 коммит произвёл GitHub
Родитель a8b33b2961 d6d5764e41
Коммит ca6a6a90b7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 53 добавлений и 0 удалений

Просмотреть файл

@ -4,6 +4,13 @@
[Full Changelog](https://github.com/mozilla/application-services/compare/v0.38.2...master)
## FxA Client
### What's new
* New `getSessionToken` method on the FxA Client that returns the stored session_token from state.
Also we now store the session_token into the state from the 'https://identity.mozilla.com/tokens/session' scope.
## Places
### What's fixed

Просмотреть файл

@ -240,6 +240,17 @@ class FirefoxAccount(handle: FxaHandle, persistCallback: PersistCallback?) : Aut
}
}
/**
* Tries to return a session token
*
* @throws FxaException Will send you an exception if there is no session token set
*/
fun getSessionToken(): String {
return rustCallWithLock { e ->
LibFxAFFI.INSTANCE.fxa_get_session_token(this.handle.get(), e)
}.getAndConsumeRustString()
}
/**
* This method should be called when a request made with
* an OAuth token failed with an authentication error.

Просмотреть файл

@ -50,6 +50,7 @@ internal interface LibFxAFFI : Library {
fun fxa_complete_oauth_flow(fxa: FxaHandle, code: String, state: String, e: RustError.ByReference)
fun fxa_get_access_token(fxa: FxaHandle, scope: String, e: RustError.ByReference): RustBuffer.ByValue
fun fxa_get_session_token(fxa: FxaHandle, e: RustError.ByReference): Pointer?
fun fxa_clear_access_token_cache(fxa: FxaHandle, e: RustError.ByReference)
fun fxa_set_push_subscription(

Просмотреть файл

@ -272,6 +272,20 @@ pub extern "C" fn fxa_get_access_token(
})
}
/// Try to get a session token.
///
/// If the system can't find a suitable token it will return an error
///
/// # Safety
///
/// A destructor [fxa_bytebuffer_free] is provided for releasing the memory for this
/// pointer type.
#[no_mangle]
pub extern "C" fn fxa_get_session_token(handle: u64, error: &mut ExternError) -> *mut c_char {
log::debug!("fxa_get_session_token");
ACCOUNTS.call_with_result_mut(error, handle, |fxa| fxa.get_session_token())
}
/// This method should be called when a request made with
/// an OAuth token failed with an authentication error.
/// It clears the internal cache of OAuth access tokens,

Просмотреть файл

@ -29,6 +29,9 @@ pub enum ErrorKind {
#[fail(display = "No stored refresh token")]
NoRefreshToken,
#[fail(display = "No stored session token")]
NoSessionToken,
#[fail(display = "Could not find a refresh token in the server response")]
RefreshTokenNotPresent,

Просмотреть файл

@ -610,6 +610,7 @@ pub struct DeviceResponseCommon {
pub struct OAuthTokenResponse {
pub keys_jwe: Option<String>,
pub refresh_token: Option<String>,
pub session_token: Option<String>,
pub expires_in: u64,
pub scope: String,
pub access_token: String,

Просмотреть файл

@ -76,6 +76,14 @@ impl FirefoxAccount {
Ok(token_info)
}
/// Retrieve the current session token from state
pub fn get_session_token(&mut self) -> Result<String> {
match self.state.session_token {
Some(ref session_token) => Ok(session_token.to_string()),
None => Err(ErrorKind::NoSessionToken.into()),
}
}
/// Initiate a pairing flow and return a URL that should be navigated to.
///
/// * `pairing_url` - A pairing URL obtained by scanning a QR code produced by
@ -199,6 +207,13 @@ impl FirefoxAccount {
self.state.scoped_keys.insert(scope, scoped_key);
}
}
// If the client requested a 'tokens/session' OAuth scope then as part of the code
// exchange this will get a session_token in the response.
if resp.session_token.is_some() {
self.state.session_token = resp.session_token;
}
// We are only interested in the refresh token at this time because we
// don't want to return an over-scoped access token.
// Let's be good citizens and destroy this access token.

Просмотреть файл

@ -200,6 +200,7 @@ mod tests {
expires_in: 6_000_000,
scope: "profile".to_owned(),
access_token: "good_profile_token".to_owned(),
session_token: None,
}));
// Then hooray it works!
client