Get user's phone number in Firefox OS - phone-number

Is there any way to fetch user’s phone number in Firefox OS?
If so, any help would be appreciated.

According to Mozilla's app permissions page, there is an permission called "phonenumberservice" but there is no information about it. Anyway, the permision is listed under the "Internal (Certified) app permissions", which means that, when available, it can only be used by "system-level apps and default apps created by Mozilla/operators/OEMs".

With Firefox 2.0 you should be able to use Mobile Identity API:
https://wiki.mozilla.org/WebAPI/MobileIdentity
https://bugzilla.mozilla.org/show_bug.cgi?id=1021594
I believe the permission is:
"permissions": {
"mobileid": {} }
And it is privileged.

So, as #Jason said, the Mobile Identity API provides this capability, and not just for certified, but for privileged applications. So it is no longer just for OEMs.
The Mozilla Wiki site shows the API:
dictionary MobileIdOptions {
boolean forceSelection = false;
};
partial interface Navigator {
Promise getMobileIdAssertion(optional MobileIdOptions options);
};
The site also provides a sample code skeleton for this:
function verifyAssertion(aAssertion) {
// Make use of the remote verification API
// and return the verified msisdn.
// NB: This is necessary to make sure that the user *really* controls this phone number!
}
// Request a mobile identity assertion and force the chrome UI to
// allow the user to change a possible previous selection.
navigator.getMobileIdAssertion({ forceSelection: true })
.then(
(assertion) => {
verifyAssertion(assertion)
.then(
(msisdn) => {
// Do stuff with the msisdn.
}
);
},
(error) {
// Process error.
};
);
For this to work, you need to add the mobileid permission in the manifest file, for example like this (I made up the description):
"permissions": {
"mobileid": {
"description": "Required for sending SMS for two factor authentication",
"access": "readonly"
}
}
PS: I made this answer, because most answers are outdated, and the one that isn't, does not contain all useful information.
References:
App Manifest Documentation
Firefox Remote Verification

Related

Teams Icon in Microsoft Teams Configurable Tab

I am building a teams app which is using a non-AAD based service to Authenticate. I would like to get the Teams Icon in my Configurable Tab. What are the option I have? I can not register an app, as the Teams app is going to be deployed on different tenants. Can I use microsoftTeams.authentication.getAuthToken for graph api(/teams/${teamsid}/photo/$value) without registering an app but on behalf of user ? or is there any easier way to get the teams icon.
const authTokenRequest: microsoftTeams.authentication.AuthTokenRequest = {
successCallback: function (token: string) {
//const decoded: { [key: string]: any; } = jwt.decode(token);
//localStorage.setItem("name", decoded.name);
localStorage.setItem("token", token);
const response = await axios.get(apiConfig.endpoint + "/api/" + functionName, {
headers: {
authorization: "Bearer " + accessToken?.token || "",
},
});
return response.data;
},
failureCallback: function (error: any) {
console.log("Failure on getAuthToken: " + error);
}
};
microsoftTeams.initialize(() => {
microsoftTeams.getContext((r) => {
microsoftTeams.authentication.getAuthToken(authTokenRequest);
});
});
Through this I get below error:
Attempting to handle auth response: error:invalid_resource|AADSTS500011: The resource principal named api://xxxxx/botid-xxxx was not found in the tenant named xxxx. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant., resource:api://xxxxx/botid-xxxx, error mapped to action:resourceDisabled
You must have your app registered to be able to use graph API. It is absolutely no problem that the app will be installed on a different tenant, you just need to select "multitenant" option when registering the app to enable this scenario.
As far as I understand, logo pictures / icons are considered company data, so you need user consent to get it. For this reason, the app needs to be registered, and the user (or user admin) must agree to give the app access to the team info when adding your app.

EdgeChromium extension chrome.tabs.query failing when only activeTabs permission is requested

I am trying to find the active tabs across all windows, actual query and action is more detailed but this demonstrates the basic problem
chrome.tabs.query({active: true}, function (tabs) { console.log(tabs); });
It seems that with Chrome and Firefox we can use that api with either activeTab or tab permission, only limitations on the search items such as url.
The chrome.tabs or browser.tabs docs only seem to indicate tab permission for some parts.
When using only activeTab permission MS Edge throws error, Chrome gives the result
Adding tabs permission and I can get the results in MS Edge
Is this a deliberate difference, or a bug, or doing something else incorrect?
Trying to ask for minimal permissions as Mozilla and Google required validation of usage with permissions with wide access.
similar to, but not the same as Why browser.tabs.query is not working in Edge Extension ?
first of all, you have to add 'tabs' permission to your manifest file like this
"permissions": [
"tabs"
]
and next use this code
let queryOptions = {
active: true,
currentWindow: true
};
chrome.tabs.query(queryOptions,function (tabs){
alert(tabs[0].url)
});
after that just remove the old extension and load new files in your extensions then observe the permission section in extension details it's should be changed and check it out.

Should a Service Worker be registered in the manifest or through a script?

Most examples of registering a Service worker do so through JavaScript. For example (From MDN):
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('service-worker.js', {
scope: './'
}).then(function (registration) {
var serviceWorker;
if (registration.installing) {
serviceWorker = registration.installing;
document.querySelector('#kind').textContent = 'installing';
} else if (registration.waiting) {
serviceWorker = registration.waiting;
document.querySelector('#kind').textContent = 'waiting';
} else if (registration.active) {
serviceWorker = registration.active;
document.querySelector('#kind').textContent = 'active';
}
if (serviceWorker) {
// logState(serviceWorker.state);
serviceWorker.addEventListener('statechange', function (e) {
// logState(e.target.state);
});
}
}).catch (function (error) {
// Something went wrong during registration. The service-worker.js file
// might be unavailable or contain a syntax error.
});
} else {
// The current browser doesn't support service workers.
}
But I noticed in the Web App Manifest standard that there is a serviceworker member:
"serviceworker": {
"src": "sw.js",
"scope": "/",
"update_via_cache": "none"
}
This is the only place I've seen this referred to.
This raises two questions for me:
1 Which approach SHOULD I use? What are the trade-offs?
The declarative benefit of the manifest approach is obvious, but if I use that approach, how do I reference the registration object in order to track events similar to the script approach? (installing | waiting | active | failed).
Assuming it IS possible to reference the registration object appropriately, can it miss events? Such as finish installing before I could register an event listener to it.
2 What are the caching implications
Since the manifest would be saved in the offline cache, and this manifest would reference the service-worker script, what are the cache implications? Does the 24 hour rule still apply assuming I do NOT store the script in the offline cache? The update_via_cache member is not a simple thing to read in the spec.
It looks like it was added to the spec back in October of 2016, and there is some background discussion in the issue tracker.
My interpretation is that the use case is providing service worker bootstrapping metadata that is relevant when installing a web app via a non-browser mechanism, e.g. via an app store. I don't see any mention of that field in the guidance about Microsoft Store ingestion, though.
So... as of right now, I am not clear that any browsers honor the serviceworker field in the web app manifest, and if your concern is having a functional service worker registration for "browser" use cases, do it using JavaScript.
Your best bet for follow ups would be to ask on the web app manifest's GitHub issue tracker.

How to access Twitter screenname, avatar when autopublish has been turned off

In Meteor, I believe ordinarily you can get the screenname of a twitter user after they've logged in with {{services.twitter.screenName}}.
However with autopublish turned off the only thing that seems to be available is {{currentUser.profile.name}} (which returns their 'full name' i.e. Kevin Rose, not krose).
How would I go about getting the screenname or avatar from a user that has logged in with Twitter, if autopublish has been removed?
You just need to set up a publish record on the server to determine what information you're going to send to the client, and then subscribe to it in a client-side startup function (or better still, iron-router).
Meteor.publish("userData", function () {
return Meteor.users.find({_id: this.userId},
{fields: {'services.twitter': 1}});
});
That will provide the services field for the logged in user in Meteor.user() once that client has subscribed to "userData" in addition to the fields that are automatically supplied.
You need to manually publish / subscribe your data. By default, only emails, username and profile fields are published for Meteor.users collection (see the docs). So you need to publish others:
Meteor.publish('userData', function() {
if(!this.userId) return null;
return Meteor.users.find(this.userId, {fields: {
services: 1,
...
}});
});
After that, subscribe to this channel on the client:
Deps.autorun(function() {
Meteor.subscribe('userData');
});

Is it possible to limit the access given by a user so that it's read-only

I'm trying to use the YouTube Data API V2.0 to pull data insights for the videos/channels of our client. I have a developer key and a token that my client generates, and successfully figured out how to retrieve that information. My problem is, when my client uses the app for YouTube token generation, we are asking for an access that means EVERYTHING and to be able to "manage" their accounts.
This is a major concern for the client and they don't want us to have this kind of complete access. Is there a way to get a token generated with only read-only permission?
Thanks very much for any help!
I have successfully used https://googleapis.com/auth/youtube.readonly as a scope; if you ask for just that scope during the initial oAuth flow (and NOT for https://googleapis.com/auth/youtube at the same time, as that is the management scope which will override the readonly scope), then you will get a 403 error whenever attempting an action that requires management permissions (inserting, uploading, updating, deleting).
The google-api clients for v3 handle this quite smoothly, if you're using them. If you have written your own oAuth flow control, just make sure you have the sole readonly scope when requesting the initial token.
EDIT IN RESPONSE TO COMMENT: To view this in action (I'll use javascript to show), you can create a simple demo using the sample code provided by the API docs. Here's the general process:
1) In the Google API console, create a 'project' and authorize the YouTube API for that project (under the Services tab). Additionally,create a client ID for web applications (under the API access tab) and add in your domain as an authorized Javascript domain.
2) On your server, create and HTML file to serve as your interface (in this sample, it is designed to let you create a new playlist and add items to it). Here's the code, straight from the docs:
<!doctype html>
<html>
<head>
<title>Playlist Updates</title>
</head>
<body>
<div id="login-container" class="pre-auth">This application requires access to your YouTube account.
Please authorize to continue.
</div>
<div id="buttons">
<button id="playlist-button" disabled onclick="createPlaylist()">Create a new Private Playlist</button>
<br>
<label>Current Playlist Id: <input id="playlist-id" value='' type="text"/></label>
<br>
<label>Video Id: <input id="video-id" value='GZG9G5txtaE' type="text"/></label><button onclick="addVideoToPlaylist()">Add to current playlist</button>
</div>
<h3>Playlist: <span id="playlist-title"></span></h3>
<p id="playlist-description"></p>
<div id="playlist-container">
<span id="status">No Videos</span>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="auth.js"></script>
<script src="playlist_updates.js"></script>
<script src="https://apis.google.com/js/client.js?onload=googleApiClientReady"></script>
</body>
</html>
3) In that same location, create the script "playlist_updates.js" with this code (again, straight from the docs):
// Some variables to remember state.
var playlistId, channelId;
// Once the api loads call a function to get the channel information.
function handleAPILoaded() {
enableForm();
}
// Enable a form to create a playlist.
function enableForm() {
$('#playlist-button').attr('disabled', false);
}
// Create a private playlist.
function createPlaylist() {
var request = gapi.client.youtube.playlists.insert({
part: 'snippet,status',
resource: {
snippet: {
title: 'Test Playlist',
description: 'A private playlist created with the YouTube API'
},
status: {
privacyStatus: 'private'
}
}
});
request.execute(function(response) {
var result = response.result;
if (result) {
playlistId = result.id;
$('#playlist-id').val(playlistId);
$('#playlist-title').html(result.snippet.title);
$('#playlist-description').html(result.snippet.description);
} else {
$('#status').html('Could not create playlist');
}
});
}
// Add a video id from a form to a playlist.
function addVideoToPlaylist() {
addToPlaylist($('#video-id').val());
}
// Add a video to a playlist.
function addToPlaylist(id, startPos, endPos) {
var details = {
videoId: id,
kind: 'youtube#video'
}
if (startPos != undefined) {
details['startAt'] = startPos;
}
if (endPos != undefined) {
details['endAt'] = endPos;
}
var request = gapi.client.youtube.playlistItems.insert({
part: 'snippet',
resource: {
snippet: {
playlistId: playlistId,
resourceId: details
}
}
});
request.execute(function(response) {
$('#status').html('<pre>' + JSON.stringify(response.result) + '</pre>');
});
}
Finally, create the file "auth.js" -- this is the code that actually does the oAuth2 flow:
// The client id is obtained from the Google APIs Console at https://code.google.com/apis/console
// If you run access this code from a server other than http://localhost, you need to register
// your own client id.
var OAUTH2_CLIENT_ID = '__YOUR_CLIENT_ID__';
var OAUTH2_SCOPES = [
'https://www.googleapis.com/auth/youtube'
];
// This callback is invoked by the Google APIs JS client automatically when it is loaded.
googleApiClientReady = function() {
gapi.auth.init(function() {
window.setTimeout(checkAuth, 1);
});
}
// Attempt the immediate OAuth 2 client flow as soon as the page is loaded.
// If the currently logged in Google Account has previously authorized OAUTH2_CLIENT_ID, then
// it will succeed with no user intervention. Otherwise, it will fail and the user interface
// to prompt for authorization needs to be displayed.
function checkAuth() {
gapi.auth.authorize({
client_id: OAUTH2_CLIENT_ID,
scope: OAUTH2_SCOPES,
immediate: true
}, handleAuthResult);
}
// Handles the result of a gapi.auth.authorize() call.
function handleAuthResult(authResult) {
if (authResult) {
// Auth was successful; hide the things related to prompting for auth and show the things
// that should be visible after auth succeeds.
$('.pre-auth').hide();
loadAPIClientInterfaces();
} else {
// Make the #login-link clickable, and attempt a non-immediate OAuth 2 client flow.
// The current function will be called when that flow is complete.
$('#login-link').click(function() {
gapi.auth.authorize({
client_id: OAUTH2_CLIENT_ID,
scope: OAUTH2_SCOPES,
immediate: false
}, handleAuthResult);
});
}
}
// Loads the client interface for the YouTube Analytics and Data APIs.
// This is required before using the Google APIs JS client; more info is available at
// http://code.google.com/p/google-api-javascript-client/wiki/GettingStarted#Loading_the_Client
function loadAPIClientInterfaces() {
gapi.client.load('youtube', 'v3', function() {
handleAPILoaded();
});
}
Note in there the OAUTH2_SCOPES constant. It's set to allow full management access, so if you then visit the html page in your browser and click on the 'authorize' link, you should see the window asking you to grant your domain access to manage your YouTube account. Do this, and then the code becomes functional ... you can add playlists and playlist items to your heart's content.
If you, however, then modify auth.js so that the OAUTH2_SCOPES looks like this:
var OAUTH2_SCOPES = [
'https://www.googleapis.com/auth/youtube.readonly'
];
and clear your cookies (to avoid inheriting the permissions you already granted ... just closing the browser and relaunching ought to be enough), then try again (visit the HTML, click the authorize link), you'll see that this time it's asking you to grant permission only to VIEW the account rather than manage it. If you grant that permission, then when you try to add a playlist through the interface you'll get an error message appearing that says you can't create the playlist.
If you're not using javascript, but instead a server-side language, as I mentioned the gapi clients are quite smooth. However, the handling of oAuth2 scope in these clients is not quite as transparent, and they're by design 'greedy' (in that, as it abstracts a service endpoint to an object, it will request the most thorough scope it needs to do any of the actions at that endpoint ... so even if you only intend to do list calls, if the service has an update action as well the client will request full management privileges). This can be modified, though, if you want to get into the client code -- or you could use it as a model for creating your own simplified client that you can granularly control in terms of scope.
That's about as thorough as I can be without knowing your underlying technologies. Hope the explanation helps!

Resources