windows 10 app development - Mediaplayer - windows-10-universal

I am using below code to play mp3 file from some url (https://domailname/a.mp3), this server required jwt token for authenticating the request.
how can i play the audio from any url which requires authentication
System.Uri manifestUri = new Uri("https://domailname/a.mp3");
mediaPlayerElement.Source = MediaSource.CreateFromUri(manifestUri);
mediaPlayerElement.MediaPlayer.Play();

You may put the token in the URL as a query parameter if under under the following circumstances described on this thread.
System.Uri manifestUri = new Uri("https://domailname/a.mp3/?jwt=jwttoken");
MediaSource instance can create from AdaptiveMediaSource. If the media is adaptive source you may try to create a AdaptiveMediaSource by CreateFromUriAsync(Uri, HttpClient) method firstly. Put the token as value of Authorization Header using the bear schema, and add the header to HttpClient by the DefaultRequestHeaders property. For this you may reference the scenario 3 of AdaptiveStreaming official sample.

Related

How to get session id in static method while making callout

I am working on something which includes LWC with tooling API. I wrote this below method which makes a callout. but when I call this method this method from lwc at that time I'm unable to get session Id, but if I call this same method from the developer console then it works fine.
Apex Code:
#AuraEnabled
public static string getList(String fieldName){
HttpRequest req = new HttpRequest();
req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId());
System.debug('res------>'+UserInfo.getSessionID());
req.setHeader('Content-Type', 'application/json');
req.setEndpoint('callout:Tooling_Query/query/?q=Select+id,Namespaceprefix,developername,TableEnumOrId+FROM+customfield+Where+developername+LIKE\'' +fieldName+ '\'');
req.setMethod('GET');
Http h = new Http();
HttpResponse res = h.send(req);
System.debug('res------>'+res.getBody());
return res.getBody();
}
When I call it from lwc it returns this
[{"message":"This session is not valid for use with the REST API","errorCode":"INVALID_SESSION_ID"}]
so, how can I get session-id from lwc, I already set up a Connected App and Named Credential by the name of Tooling_Query
and add URL to remote sites.
please help me here.
You can't. Your Apex code called in a Lightning Web Components context cannot get an API-enabled Session Id. This is documented in the Lightning Web Components Dev Guide:
By security policy, sessions created by Lightning components aren’t enabled for API access. This restriction prevents even your Apex code from making API calls to Salesforce. Using a named credential for specific API calls allows you to carefully and selectively bypass this security restriction.
The restrictions on API-enabled sessions aren’t accidental. Carefully review any code that uses a named credential to ensure you’re not creating a vulnerability.
The only supported approach is to use a Named Credential authenticated as a specific user.
There is a hack floating around that exploits a Visualforce page to obtain a Session Id from such an Apex context. I do not recommend doing this, especially if you need to access the privileged Tooling API. Use the correct solution and build a Named Credential.

Graph SDK OAUTH ADAL client credentials for reuse? later

So we have an application that allows you to create a xml file that runs the app again at a later stage (which may or may not have a user in attendance). Files are stored on the user cloud drive platform of choice. So the process is
Workflow 1
Authenticate to cloud with User 1 details/input
Select files to Download and use
Save and encrypt file metadata and Refresh token to xml file. (app workflow 1)
Workflow 2 ( can be repeated multiple thousands of times)
Send xml file to another pc with User 2. (either by email or remotely through a console
that pc then runs under user 2
start app
App authenticates automatically using refresh token saved in xml file with no user input (as there is a very high chance of the user who created workflow 1 not being in the same city as where workflow 2 is running
Downloads files
applies files (app workflow 2)
PROBLEM
all other platforms we cater for (Dropbox and google and onedrive) gives us access to the refresh token and allow us to authenticate with it again , however the onedrive for business (graph sdks) give us a Token cache which is session based?
Questions
So I need to know how I can get the refresh token from the Token Cache so we can reuse it at a later stage. (yes I'm aware that it will expire after 6 months which is acceptable) .
When i have the refresh token how do initiate a call to refresh the token
Further note - I have managed to handle all platforms before Within silverlight (where the sdks are not supported) through directly calling the rest api calls but we are converting our solution to WPF and would want to use the sdks
thanks
I assume you were developing Microsoft Graph SDK when you mentioned graph sdks.
AFAIK, this library does not include any default authentication implementations. Instead, the user will want to authenticate with the library of their choice, or against the OAuth endpoint directly, and built-in DelegateAuthenticationProvider class to authenticate each request.
And if you were authenticating Azure AD with Active Directory Authentication Library, you can use the default token cache which use memory to store the cache or you can implement the token cache based on your requirement.
So I need to know how I can get the refresh token from the Token Cache so we can reuse it at a later stage. (yes I'm aware that it will expire after 6 months which is acceptable) .
When you using the ADAL library, there is no need to get the refresh token manually, it will handle for us to renew the access token if the refresh token is existed.
When i have the refresh token how do initiate a call to refresh the token
If you want to perform the request yourself to refresh the access token, you can refer the request below, and more detail you can refer this document.
POST /{tenant}/oauth2/token HTTP/1.1
Host: https://login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&refresh_token=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq...
&grant_type=refresh_token
&resource=https%3A%2F%2Fservice.contoso.com%2F
&client_secret=JqQX2PNo9bpM0uEihUPzyrh // NOTE: Only required for web apps
OK so the answer is taking the tokencache from the PublicIdentityApp and serializing as below.
var tokenCache = _app.UserTokenCache;
var tokenBytes = tokenCache.Serialize();
var tokenString = Convert.ToBase64String(tokenBytes);
And deserializing it later.
_app = new Microsoft.Identity.Client.PublicClientApplication(ClientID);
var array = Convert.FromBase64String(bytestring);
_app.UserTokenCache.Deserialize(array);
authHelper = new AuthenticationHelper(_app);
var authorise = await authHelper.GetTokenForUserAsync()

How to generate OAuth2.0 Bearer when calling App Engine Endpoints API?

I am providing a REST API via App Engine. I used Cloud Endpoints to generate it, although the client will not be mobile Android/iPhone but rather a known web server. Since I am familiar with this server (it is part of my application), I decided to use Service Account authorization in order to authorize the API calls (In addition, I will do IP validation, but that's beside the point).
I made all the necessary arrangement, created a Google developer project, generated a service account id (and email), with a p12 file, and added all the annotations needed on the server side (including a User object in the implementing function).
Now I want to implement a call to this API, and in order for it to work, I need to include a proper authorization header in my request.
When working with Google APIs, the client libraries generate some Credential object which you later need to pass in building some Service object, which represents a Google API you wish to call. For example, if you want to access Drive API in Java, you will do:
Drive drive = new Drive.Builder(Globals.httpTransport, Globals.jsonFactory, credential).build();
Where credential object is the object I previously build as follows:
credential = new GoogleCredential.Builder().setTransport(Globals.httpTransport)
.setJsonFactory(Globals.jsonFactory)
.setServiceAccountId(serviceAccountEmail)
.setServiceAccountScopes(scopes)
.setServiceAccountUser(serviceAccountUser)
.setServiceAccountPrivateKeyFromP12File(file(serviceAccountPrivateKeyP12File))
.build();
However, in my case, the client is not calling a Google API, but rather my App Engine REST API. How do I go about generating (or using the credential object I created to obtain) a proper Authorization header?
You can find some documentation in the readme.html file that is generated alongside the bindings, and here.
You can get the following account information in the console, "Apis & Auth", "Credentials". Here you need to paste "Email Address" of the service account. Your #Api annotation should include the account's "Client Id" in the "clientIds" parameter.
String accountEmail = "your-service-account#developer.gserviceaccount.com";
String keyFilePath = "your-key-file.p12";
This is the minimum authorization scope that is required for Cloud Endpoints API. It only allows the app to access the user's e-mail address. Your #Api annotation should list it in the "scopes" parameter.
String emailScope = "https://www.googleapis.com/auth/userinfo.email";
Then you need to create some support objects and the credential. GsonFactory can be replaced with JsonFactory if you prefer.
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
GsonFactory gsonFactory = new GsonFactory();
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(gsonFactory)
.setServiceAccountId(accountEmail)
.setServiceAccountScopes(Collections.singleton(emailScope))
.setServiceAccountPrivateKeyFromP12File(new File(keyFilePath))
.build();
And finally create your API client. Replace YourApi with the client from the generated bindings. If you want to test against the dev AppServer, you can call .setRootUrl(yourDevServerUrl + "/_ah/api") on the builder.
YourApi client = new YourApi.Builder(httpTransport, gsonFactory, credential)
.setApplicationName("YourClientName")
.build();

How do I protect my API that was built using Google Cloud Endpoints?

The API is a backend to a mobile app. I don't need user authentication. I simply need a way to secure access to this API. Currently, my backend is exposed.
The documentation seems to only talk about user authentication and authorization, which is not what I need here. I just need to ensure only my mobile app can talk to this backend and no one else.
Yes, you can do that: use authentication to secure your endpoints without doing user authentication.
I have found that this way of doing it is not well documented, and I haven't actually done it myself, but I intend to so I paid attention when I saw it being discussed on some of the IO13 videos (I think that's where I saw it):
Here's my understanding of what's involved:
Create a Google API project (though this doesn't really involve their API's, other than authentication itself).
Create OATH client ID's that are tied to your app via its package name and the SHA1 fingerprint of the certificate that you will sign the app with.
You will add these client ID's to the list of acceptable ID's for your endpoints. You will add the User parameter to your endpoints, but it will be null since no user is specified.
#ApiMethod(
name = "sendInfo",
clientIds = { Config.WEB_CLIENT_ID, Config.MY_APP_CLIENT_ID, Config.MY_DEBUG_CLIENT_ID },
audiences = { Config.WEB_CLIENT_ID }
// Yes, you specify a 'web' ID even if this isn't a Web client.
)
public void sendInfo(User user, Info greeting) {
There is some decent documentation about the above, here:
https://developers.google.com/appengine/docs/java/endpoints/auth
Your client app will specify these client ID's when formulating the endpoint service call. All the OATH details will get taken care of behind the scenes on your client device such that your client ID's are translated into authentication tokens.
HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = new JacksonFactory();
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience( ctx, Config.WEB_CLIENT_ID );
//credential.setSelectedAccountName( user ); // not specify a user
Myendpoint.Builder builder = new Myendpoint.Builder( transport, jsonFactory, credential );
This client code is just my best guess - sorry. If anyone else has a reference for exactly what the client code should look like then I too would be interested.
I'm sorry to say that Google doesn't provide a solution for your problem (which is my problem too).
You can use their API key mechanism (see https://developers.google.com/console/help/new/#usingkeys), but there is a huge hole in this strategy courtesy of Google's own API explorer (see https://developers.google.com/apis-explorer/#p/), which is a great development tool to test API's, but exposes all Cloud Endpoint API's, not just Google's services API's. This means anyone with the name of your project can browse and call your API at their leisure since the API explorer circumvents the API key security.
I found a workaround (based on bossylobster's great response to this post: Simple Access API (Developer Key) with Google Cloud Endpoint (Python) ), which is to pass a request field that is not part of the message request definition in your client API, and then read it in your API server. If you don't find the undocumented field, you raise an unauthorized exception. This will plug the hole created by the API explorer.
In iOS (which I'm using for my app), you add a property to each request class (the ones created by Google's API generator tool) like so:
#property (copy) NSString *hiddenProperty;
and set its value to a key that you choose. In your server code (python in my case) you check for its existence and barf if you don't see it or its not set to the value that your server and client will agree on:
mykey,keytype = request.get_unrecognized_field_info('hiddenProperty')
if mykey != 'my_supersecret_key':
raise endpoints.UnauthorizedException('No, you dont!')
Hope this puts you on the right track
The documentation is only for the client. What I need is documentation
on how to provide Service Account functionality on the server side.
This could mean a couple of different things, but I'd like to address what I think the question is asking. If you only want your service account to access your service, then you can just add the service account's clientId to your #Api/#ApiMethod annotations, build a GoogleCredential, and invoke your service as you normally would. Specifically...
In the google developer's console, create a new service account. This will create a .p12 file which is automatically downloaded. This is used by the client in the documentation you linked to. If you can't keep the .p12 secure, then this isn't much more secure than a password. I'm guessing that's why this isn't explicitly laid out in the Cloud Endpoints documentation.
You add the CLIENT ID displayed in the google developer's console to the clientIds in your #Api or #ApiMethod annotation
import com.google.appengine.api.users.User
#ApiMethod(name = "doIt", scopes = { Constants.EMAIL_SCOPE },
clientIds = { "12345678901-12acg1ez8lf51spfl06lznd1dsasdfj.apps.googleusercontent.com" })
public void doIt(User user){ //by convention, add User parameter to existing params
// if no client id is passed or the oauth2 token doesn't
// match your clientId then user will be null and the dev server
// will print a warning message like this:
// WARNING: getCurrentUser: clientId 1234654321.apps.googleusercontent.com not allowed
//..
}
You build a client the same way you would with the unsecured version, the only difference being you create a GoogleCredential object to pass to your service's MyService.Builder.
HttpTransport httpTransport = new NetHttpTransport(); // or build AndroidHttpClient on Android however you wish
JsonFactory jsonFactory = new JacksonFactory();
// assuming you put the .p12 for your service acccount
// (from the developer's console) on the classpath;
// when you deploy you'll have to figure out where you are really
// going to put this and load it in the appropriate manner
URL url = getClass().class.getResource("/YOURAPP-b12345677654.p12");
File p12file = new File(url.toURI());
GoogleCredential.Builder credentialBuilder = new GoogleCredential.Builder();
credentialBuilder.setTransport(httpTransport);
credentialBuilder.setJsonFactory(jsonFactory);
//NOTE: use service account EMAIL (not client id)
credentialBuilder.setServiceAccountId("12345678901-12acg1ez8lf51spfl06lznd1dsasdfj#developer.gserviceaccount.com"); credentialBuilder.setServiceAccountScopes(Collections.singleton("https://www.googleapis.com/auth/userinfo.email"));
credentialBuilder.setServiceAccountPrivateKeyFromP12File(p12file);
GoogleCredential credential = credentialBuilder.build();
Now invoke your generated client the same way
you would the unsecured version, except the builder takes
our google credential from above as the last argument
MyService.Builder builder = new MyService.Builder(httpTransport, jsonFactory, credential);
builder.setApplicationName("APP NAME");
builder.setRootUrl("http://localhost:8080/_ah/api");
final MyService service = builder.build();
// invoke service same as unsecured version

Custom SignIn & SignUp on RESTlet + GAE/J?

I am currently working on a small project using RESTlet on Google App Engine/Java.
I was searching.. searching.. and couldn't find the exact or understandable solutions for my doubts.
My question is that How am I suppose to implement my own SignIn & SignUp module without using google's UserService or Spring Security??
Is there any actual sample code available??
I mean SignUp part is just a simple JDO insert & select module. let's just say I've done it.
How am I supposed to handle each user's request session and authentication??
I am thinking about using HTTPS on every request.
Any suggestions or help would be really appreciated!
Thanks in advance.
In Restlet, you have security support on both client and server sides. On client side, you can specify security hints using the ChallengeResponse entity. This feature is open and you can specify the authentication type you want. In the following code, I use an http basic authentication based on username / password:
ClientResource cr = new ClientResource(uri);
ChallengeScheme scheme = ChallengeScheme.HTTP_BASIC;
ChallengeResponse authentication = new ChallengeResponse(
scheme, "username", "password");
cr.setChallengeResponse(authentication);
Restlet will automatically build necessary headers in the corresponding request. You can note that Restlet supports a wide range of authentication types through its extensions. I know that some work is done at the moment to support OAuth v2 (see http://wiki.restlet.org/developers/172-restlet/257-restlet/310-restlet.html).
On the server side, you need to secure accesses at routing level using the ChallengeAuthenticator entity, as described below. This can be done within your Restlet application:
public Restlet createInboundRoot() {
Router router = new Router(getContext());
ChallengeAuthenticator guard = new ChallengeAuthenticator(getContext(),
ChallengeScheme.HTTP_BASIC, "realm");
guard.setVerifier(verifier);
guard.setEnroler(enroler);
guard.setNext(router);
return guard;
}
Like for client side, this support is generic and is based on two interfaces that need to be specified on the guard:
The verifier one to check if authentication is successful
The enroler one to fill roles for the authenticated user
You can notice that same security technologies need to be use on both sides...
If you want to manage authentication session for user, you need to implement it by yourself using cookies.
When authentication successes on server side, you can return a cookie containing a security token that allows you checking the user from your database (for example). Some code like below can implement that:
CookieSetting cookie = new CookieSetting(0,
SECURITY_COOKIE_NAME, securityToken);
Series<CookieSetting> cookieSettings = response.getCookieSettings();
cookieSettings.clear();
cookieSettings.add(cookie);
You can extend for example the SecretVerifier class of Restlet to add a test on security data received and add this code when receiving the security cookie.
On client side, you need to add hints for authentication the first time and then re send the security cookie following times, as described below:
ClientResource clientResource = (...)
(...)
Cookie securityCookie = new Cookie(0,
SECURITY_COOKIE_NAME, securityToken);
clientResource.getRequest().getCookies().clear();
clientResource.getRequest().getCookies().add(securityCookie);
Hope it will help you!
Thierry
If you are interested in re-using social accounts, you need to integrate with each one like facebook oauth
And/Or use the app engine authentication via OpenID
Both ways define an API to authenticate a client, you can use the UserService or manage your own state via cookies.

Resources