I am using Skype Web SDK to get a user's contact list in the following manner.
Skype.initialize({
apiKey: 'a42fcebd-5b43-4b89-a065-74450fb91255',
}, function (api) {
var Application = api.application;
var client = new Application();
client.signInManager.signIn({
username: sip,
password: pwd
})
This works fine when I provide the username(sip) and password. However, when I reload the page, I have to provide the credentials again because the app re-initializes. Is there a way to maintain the user's sessions for a while after the initial login so that the page refreshes wouldn't need ask for credentials again?
I have looked through the samples and docuementation that Microsoft has and couldn't find a way. I've also tried to store the client object in the localStorage after the initialization and sign in, but when I tried to reuse the object from localStorage to get the contact list, it did not work.
http://officedev.github.io/skype-docs/Skype/WebSDK/model/api/interfaces/jcafe.signinmanager.html#signin last example explains that you can store oauth token and use it as unexpired token.
To connect to an existing app's event channel, specify id of that app:
sm.signIn({
username: "user1#company.com",
password: "password1",
id: "273867-234235-45346345634-345"
});
To sign in to Skype for Business Online using OAuth while handling the
logic of retrieving OAuth tokens yourself:
sm.signIn({
client_id: '123-456',
origins: [ 'https://webdir.online.lync.com/AutoDiscover/AutoDiscoverservice.svc/root' ],
cors: true,
get_oauth_token: function(resource) {
// Return a valid unexpired token for the specified resource if you already have one.
// Else, return a promise and resolve it once you have obtained a token.
return 'Bearer eyJ0e...';
}
});
Related
I have an application that uses Google APIs in some places, and I want to avoid having the user login every time. Currently, I only receive a Google access token in the response, not a refresh token. How can I obtain the refresh token?
This is the function I use to when the user click to login with google:
authenticate() {
const client = google.accounts.oauth2.initTokenClient({
client_id: 'MY_CLIENT_ID',
scope: [
"All_NECESSARY_SCOPES",
].join(" "),
callback: (res) => {
this.accessToken = res.access_token
this.loadClient()
}
})
client.requestAccessToken()
},
It works for getting the access token. And I need the refresh token, Please Help Me :)
Client side JavaScript does not return a refresh token. It would be a security risk.
If you want a refresh token you need to use a server sided language like Node.js
I'm currently integrating a frontend with a 3rd party backend that offers sign-in with social media. I'm using the Google JS SDK https://accounts.google.com/gsi/client which works fine with the one-tap login as it returns an ID Token which the backend requires. However, the downside is, if the user doesn't have a Google session, the prompt won't show.
If the user isn't logged in to Google, I've managed to prompt a login form and request a token on successful login, however, it only returns an access token. Is any way to request an ID token?
Example:
google.accounts.id.prompt(async notification => {
if (notification.getNotDisplayedReason() === 'opt_out_or_no_session') {
const tokenClient = google.accounts.oauth2.initTokenClient({
client_id: googleClientId,
scope: 'openid email profile',
})
tokenClient.callback = response => {
// response only has access token and no ID Token
}
tokenClient.requestAccessToken({ prompt: 'consent' })
}
window.addEventListener('load', () => {
google.accounts.id.initialize({
client_id: googleClientId,
callback: (user: CredentialResponse) => {
const { credential: idToken } = user
// I need idToken in the above requestAccessToken too
},
})
})
})
You are initializing two different namespaces in the example you have provided. The first one initializes oauth2 namespace, which starts the authorisation flow. This flow results in the acquisition of an access_token as you've realised.
The second one initializes the id namespace, which is responsible from the authentication flow. This returns an id_token, which is what you need indeed.
To keep using authentication flow beyond the capability of one-tap log in, you can render a Sign-In with Google button using the authentication initialisation. Simple initialise google.account.id.initialize() as you would. Then call one-tap prompt.
google.accounts.id.prompt();
Then in addition to that, you can render the button:
google.accounts.id.renderButton(document.getElementById("g-btn"), {
type: "standard",
logo_alignment: "left"
});
And
<div class="google-button" id="g-btn"></div>
Regardless of how the user decides to sign-in, it'll lead to the same callback method you've defined in the initialize() call.
I started implementing 2 years ago my custom authentication in azure mobile service with node.js to use it in my jquery/cordova appery.io app. I have a database with users, passwords, etc and a login api in node.js backend that generates a valid jwt like this:
http://www.thejoyofcode.com/Exploring_custom_identity_in_Mobile_Services_Day_12_.aspx
http://chrisrisner.com/Version-1-of-the-Mobile-Services-JWT-token-has-been-deprecated
But now i have been migrated to azure app service and don´t know how to implement custom authetication with javascript.
At the examples above:
"iss":"urn:microsoft:windows-azure:zumo",
"ver":2,
"aud":aud,
But i have read that "aud" and "iss" must be my azure website and "sub" my own userId, to generate a valid jwt in my custom auth to use it in azure. Is it right?
https://shellmonger.com/2016/04/08/30-days-of-zumo-v2-azure-mobile-apps-day-5-custom-authentication/
The important thing is the token. There are some requirements for using 3rd party tokens with an Azure Mobile App:
It must follow the Json Web Token format
The user Id must be in the subject (sub) field
The audience (aud) and issuer (iss) must be known and configured
I do a call to my login API with ajax post and obtain a valid JWT token (http://jwt.io), but i don´t know the correct process to login and use azure services because i don´t know the correct way to use it on my app. I have changed MobileServices.Web.min.js to azure-mobile-apps-client.js in the app.
https://github.com/Azure/azure-mobile-apps-js-client
Can i use the jwt token created in azure node.js or exchange it for a session token and use client.login() method by JS SDK?
EDIT:
I see the light again adding to ajax POST
headers: {'X-ZUMO-AUTH': usuarioToken},
So my "authenticated users only" api works again with the old MobileServices.Web.min.js! It also works perfect with invokeApi method:
var mobileClient = new WindowsAzure.MobileServiceClient(urlApp,keyApp);
mobileClient.currentUser = {
userId: myCustomUserId,
mobileServiceAuthenticationToken: myCustomToken
};
mobileClient
.invokeApi('data', {
method: 'POST',
headers: {'X-ZUMO-AUTH': myCustomToken},
body: JSON.stringify(theData)
}) //end invokeApi
.done(
function (response) {
alert(response);
},
function (error) {
alert("error"));
}
); //end done
The mobileClient generated contains this data:
mobileClient= {"applicationUrl":"https://xxx.azure-mobile.net/","applicationKey":"hGhzxxx","version":"ZUMO/1.2 (lang=Web; os=--; os_version=--; arch=--; version=1.2.21003.0)","currentUser":{"userId":"Custom:25F600BB-xxxx-xxxx-xxxx-8329BCCF31D2","mobileServiceAuthenticationToken":"ey__rest of jwt token"},"_serviceFilter":null,"_login":{"_loginState":{"inProcess":false,"cancelCallback":null},"ignoreFilters":true},"push":{"_apns":null,"_gcm":null,"_registrationManager":null}}
I will try again wiht the new azure-mobile-apps-client.js
Any comment will be welcome
I'm using auth0 to authenticate my logins to my Single Page App (built on React). I'm mostly using the base API calls (listed here).
The process I'm using is:
get username/email and password when the user enters them on my app's login page
Send a POST request to /oauth/ro with those values - here is that code:
export const login = (params, err) => {
if (err) return err
const {email, password} = params
const {AUTH0_CLIENT_ID, AUTH0_DOMAIN} = process.env
return fetch(`${AUTH0_DOMAIN}/oauth/ro`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
'client_id': AUTH0_CLIENT_ID,
'username': email,
'password': password,
'connection': 'Username-Password-Authentication',
'grant_type': 'password',
'scope': 'openid',
'device': '',
'id_token': ''
})
})
.then(response => response.json())
.then(json => {
const {id_token, access_token} = json
setCookieValue('id_token', id_token) // utility function I wrote
return getProfile(access_token)
.then(data => {
const {user_id, email: emailAddress, picture, name} = data
return {id_token, user_id, emailAddress, picture, name}
})
})
.catch(error => console.log(`ERROR: ${error}`))
}
This is all sent through Redux and the user is logged in (assuming the username/password was correct).
However, I'm trying to figure out how to persist the login when refreshing the page/coming back to the app. I'm saving the id_token (which is a JWT) in the browser's cookies and can fetch this when the app renders server-side. I can decode the JWT and get the payload (sub is the user ID from auth0). However, to get the profile data I need the access_token which Auth0 provides when using the /oauth/ro POST request. Obviously, if the JWT token has expired then it will just reject it and keep the user logged out.
Here is my code to decode the JWT (happens on app render):
const ID_TOKEN = req.cookies.id_token || false
if (ID_TOKEN) {
verifyJwt(ID_TOKEN, (err, decoded) => {
if (err) { console.log(`JWT Verification error: ${err}`) }
else {
const {sub} = decoded
getProfile(sub).then(data => store.dispatch(fetchUserDetails(data))) // fails as `sub` (the user id) is not the `access_token` which it requires
}
})
}
I have tried using the /oauth/ro call again, but this time specifying "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer" and using the id_token retrieved from the cookies, and specifying a device. However, when I do this call, I get this error from Auth0:
{
"error": "invalid_request",
"error_description": "there is not an associated public key for specified client_id/user_id/device"
}
So my question is, what API call do I need to make to get the access_token from the id_token JWT?
Also, as a bonus - when I do the POST request to login, the password is being transfered over plaintext. How would I encrypt this when sending to auth0 so they can decrypt it back? I assume it involves using the client_secret which auth0 provide but I'm not sure how to go about doing that.
The ability to refresh a token programmatically without any type of user interaction is accomplished through the use of refresh tokens. However, this is not applicable for browser-based applications because refresh tokens are long-lived credentials and the storage characteristics for browsers would place them at a too bigger risk of being leaked.
If you want to continue to use the resource owner password credentials grant you can choose to ask the user to input the credentials again when the tokens expire. As an alternative, upon authentication you can obtain the required user information and initiate an application specific session. This could be achieved by having your server-side logic create an application specific session identifier or JWT.
You can also stop using the resource owner password credentials grant and redirect the user to an Auth0 authentication page that besides returning the tokens to your application would also maintain an authenticated session for the user, meaning that when the tokens expired and your application redirected again to Auth0, the user might not need to manual reenter credentials because the Auth0 session is still valid.
In relation to the password being sent in plaintext; the resource owner endpoint relies on HTTPS so the data is encrypted at the protocol level. You must also use HTTPS within your own application for any type of communication that includes user credentials of any kind.
Also note that you can control what's returned within the ID token through the use of scopes, depending on the amount of information in question you might not even need to make additional calls to get the user profiles if you signal that you want that information to be contained within the ID token itself.
I need to retrieve some data from Google Search Console (Webmaster Tools) using a service account.
So far I've been able to retrieve an access_token for the service account which I need to append to the url of the request. The problem is that I can't find a way to do so, this is the code i'm using:
function retrieveSearchesByQuery(token)
{
gapi.client.webmasters.searchanalytics.query(
{
'access_token': token,
'siteUrl': 'http://www.WEBSITE.com',
'fields': 'responseAggregationType,rows',
'resource': {
'startDate': formatDate(cSDate),
'endDate': formatDate(cEDate),
'dimensions': [
'date'
]
}
})
.then(function(response) {
console.log(response);
})
.then(null, function(err) {
console.log(err);
});
}
This is the url called by the function:
https://content.googleapis.com/webmasters/v3/sites/http%3A%2F%2Fwww.WEBSITE.com/searchAnalytics/query?fields=responseAggregationType%2Crows&alt=json"
Instead it should be something like this:
https://content.googleapis.com/webmasters/v3/sites/http%3A%2F%2Fwww.WEBSITE.com/searchAnalytics/query?fields=responseAggregationType%2Crows&alt=json&access_token=XXX"
The gapi.client.webmasters.searchanalytics.query doesn't recognize 'access_token' as a valid key thus it doesn't append it to the url and that's why I get a 401 Unauthorized as response.
If I use 'key' instead of 'access_token' the parameter gets appended to the url but 'key' is used for OAuth2 authentication so the service account token I pass is not valid.
Does anyone have a solution or a workaround for this?
If your application requests private data, the request must be authorized by an authenticated user who has access to that data. As specified in the documentation of the Search Console API, your application must use OAuth 2.0 to authorize requests. No other authorization protocols are supported.
If you application is correctly configured, when using the Google API, an authenticated request looks exactly like an unauthenticated request. As stated in the documentation, if the application has received an OAuth 2.0 token, the JavaScript client library includes it in the request automatically.
You're mentioning that you have retrieved an access_token, if correctly received, the API client will automatically send this token for you, you don't have to append it yourself.
A very basic workflow to authenticate and once authenticated, send a request would looks like the following code. The Search Console API can use the following scopes: https://www.googleapis.com/auth/webmasters and https://www.googleapis.com/auth/webmasters.readonly.
var clientId = 'YOUR CLIENT ID';
var apiKey = 'YOUR API KEY';
var scopes = 'https://www.googleapis.com/auth/webmasters';
function auth() {
// Set the API key.
gapi.client.setApiKey(apiKey);
// Start the auth process using our client ID & the required scopes.
gapi.auth2.init({
client_id: clientId,
scope: scopes
})
.then(function () {
// We're authenticated, let's go...
// Load the webmasters API, then query the API
gapi.client.load('webmasters', 'v3')
.then(retrieveSearchesByQuery);
});
}
// Load the API client and auth library
gapi.load('client:auth2', auth);
At this point, your retrieveSearchesByQuery function will need to be modified since it doesn't need to get a token by argument anymore in order to pass it in the query. The JavaScript client library should include it in the request automatically.
You can also use the API Explorer to check what parameters are supported for a specific query and check the associated request.
If you need to use an externally generated access token, which should be the case with a Service Account, you need to use the gapi.auth.setToken method to sets the OAuth 2.0 token object yourself for the application:
gapi.auth.setToken(token_Object);