Generate file through WCF, download through ASP.NET with access validation - c#

I need to implement a operation in which the user requests a file which takes sometime to be generated ( 2 - 4 minutes). After that, the user needs to download the file, preferentially through ASP.NET ( to make use of the browser download facility). Only the specified user can download this file.
Here is how i tried to do it:
First, I built a duplex wcf service. The user calls it with the data it needs and then it starts the file generation, notifying the progress through the callback channel. In the end, the service is supposed to send to the user a url, token which he will use to download the file. This part works fine.
I saved the file to a temp folder in the asp_data folder, to prevent it from being accessed directly. Then I created a aspx page to receive the token ( whatever it is), validate it against the current user, the defined expiration, and replace the response with the file.
Then the things got messy. I do not know the right way to generate the token through WCF, return it to the client and use it the access the download page. I tried two different approaches, but I think I'm giving up on both:
Generate a guid for the file, encrypt it inside a FormsAuthenticationTicket (with the user information and expiration) and send it to the client. The client then uses the ticket encrypted string as the token to the download page, which validates the user in the ticket against the current one , check the expiration, extracts the guid and sends the file back. The problem is that the generated encrypted string gets really big, unusable in a url.
Generate a guid for the file, save it in ticket ( with validation data and the path to the file) in the httpcontext session. the wcf service then passes the guid to the client, who uses it to access the download page. The download page checks the session, retrieves the ticket, serves the file. The problem is I'm having some trouble acessing the session in the WCF operation. The user requests the file, the server starts a thread to generate the file and make the callback calls, so the first server call returns (nothing). When I've finish generating the file with success, the callback thread tries to access the session, save the ticket and return the guid to the user in a 'FinishOperationXXX' callback. I cant access the session, though, because it seems to be no longer available to the callback thread.
I don't want to use a database to do this, and I'm trying to avoid downloading the file throught the WCF itself, but I need to get this working. I guess I'll manage to do it somehow, but I wonder:
Am I doing this the hard way?
Do anyone have a clue about implementing something alike?

Why do you need encryption and a FormsAuthenticationTicket?
Wouldn't it work well enough to just name the file with the type of file, user's userid and a timestamp (filetype_userid_timestamp.ext) and only allow users to download files that contain their userid in the middle field?
(type of file being different for each page doing this in case you had more than one...)
Authentication for the user should already be handled by the session right?

Related

There is some method for prevent multi-device login on Playfab?

Are there some method to prevent multi-device login using Playfab?
I have a card game with Playfab authentication. I must have a login control for cheaters, I would like to have only one login for each player and for each of their device, if a user login with a new device, the old device must be logged out automatically.
I try to change the session ticket or entity ticket at runtime in my c# code but I read in another post that Playfab is designed for multi-device login, in fact there isn't any function to change the session or entity ticket.
I saw somebody using CloudScript, but I don't know how it works and I don't know if it is heavy to do this.
A possible option could be to execute a custom cloudscript function on game startup to save on Player Data the current deviceId. Every request will have to be validated using this "token", so client will have to pass this kind of information at every call.
If deviceId matches with the one saved on server, execution continues smoothly, otherwise an error should be passed as response to the client. This error can be used to show a popup on client to inform user for example.
At every login, deviceId is updated on PlayerData. In this way, you know it is read on every request, but written only once (on game startup). Also, only the last logged will be able to get server data. Other devices won't be able to get proper responses from server until the app is rebooted.

Refresh identity token from client from code

I am using the fine-uploader with an asp.net mvc backend to upload files directly to an azure blob-storage. The asp.net-server works as the azure-signature-endpoint(sas). This is all secured with an identityserver3 and here comes the problem: The identity_tokens lifetime is set to 5 minutes(as default). And I want the SAS endpoint to be only called authorized. So a user can only access its own data. But after I have the upload running for the set 5 minutes, it breaks. Of course, because it is not authorized and it returns the login-page from the identity-server(which the fine-uploader, of course, can't handle).
It would be easy to solve this problem, by either setting the lifetime from the token to something higher(but this is unreliable as the upload could take hours or days), or disable the lifetime(yeah would work. But I guess the lifetime has a reason to exist).
So my 2 ideas would be:
to just authorize the user once(when he starts the download)
or to refresh the token by code every time the signature gets generated.
First approach
Can I just set a boolean like user is authorized and if this boolean is set just skip authorization and just return the signature or how could I achieve this
Second approach
How would I do this?
Don't use the id token for API access, an instead use access token. Access tokens are for resources (APIs), whilst id_tokens are purely for authentication. The id_token is only meant to be used to provide the RP with means of knowing who the user is - hence no need for long time span. It's only there for converting into a user session (cookie/principal).
With access tokens you have several approaches for keeping a valid token at a client; either by fetching new ones using the client credentials flow or by using the refresh token approach.
I believe there are samples of both in the samples repo of IdentityServer.
Samples repo link

Users permission to files

our team just work on a project which works on an Automation system. we use ASP.NET technology.here is my Question:
We have some users that could access to some Official letter on a Directory.for example here is a link: 192.168.1.1/home/Documents/1/Example.DOC
each user have it's own user and password and they are on local office network. if a user could use the link above so he can copy and paste it on browser and access to files. we need some solution that denied users to access file directly in our server.so our application should get the file from directory and return it as new link to user.so if the user copy/paste it again he can not get the file because the virtual link has absolute. what solution do you recommend? Thanks all.
User handler (.ashx) to return a file. The handler can check if user has permission for file. If the file should be downloaded only once lazy method (without some file ticket system) is to limit download availability to just few minutes - i.e. make a redirect to .ashx from your page and add symmetrically encrypted timestamp
Response.Redirect(#"/GetFile.ashx?Timestamp=[Symmetrically Encrypted Current Date and Time]&FileName=Example.doc");
And in handler check if timestamp is valid (not older than few minutes) and serve the file.

how Login to a website using c# and read the contents of the logged in webpage (stream)?

I would like to know if its possible at all for a website developed using asp.net , and, if so, could someone please give me a few pointers on how to do it?
There are different ways you can do this .If you are doing it with ASP.NET I would suggest you web-services. People using API can pass username and encoded password over network .Share a secret key with the client for encoding passwords.
This might help http://blogs.sitepoint.com/single-sign-web-service-asp-net/ .
By passing a username and a hashed password of the user to method u can authenticate. The method queries the database to see if a row exists that contains both the username and the password. If a row is found, the user is authenticated, return true. Otherwise, we've been given incorrect credentials, and a false is returned.
If you need to return a stream you can build the stream by reading some file Using File.IO StreamReader and return it as a response.
If you want to take advantage of a third party website, you may want to use a WebClient class which will permit to fetch webpages and keep cookies in a CookieContainer class.
By making different web requests you will be able to POST (authentication) forms or even open HTTP stream for media elements such as videos. It's a bit hard to parse HTML but it's doable.
You just need to think as a web browser.
By the way, don't forget not to scrap elements under copyright.

reusable "save credentials" dialog (like IE's or Vista's) in .NET or Win32

Lately I've been working in an office with a wireless network which uses an annoying authentication scheme: every few hours, you need to open up a browser and type a username/password into an authentication web page, or you lose network access. (When the time expires, your next browser request will redirect to the auth page, and if your creds pass muster, then you'll be redirected back to the page you were trying to get to originally).
This kind of annoyance may be OK for an airport or coffee shop wireless, but in an office it's infuriating-- especially if you're working with network services (e.g. SVN, email) which suddenly stop working every few hours unless you bring up a browser.
So I have written a tiny C# console app which will log in for me by sending an HTTP request to the login form with my credentials.
This is obviously insecure-- my password is sitting inside my source code for all to see. I'd prefer to be able to save my credentials using the same mechanism that IE, for example, uses to save and re-fill passwords in web forms.
Ideally, I'd like a re-usable component for entering, saving, and retrieving credentials(including the UI with an optional "save creds" checkbox) so that my app can simply do something like this (in pseudocode):
// retrieve any saved credentials from some secure place
Credentials creds = GetCreds(some parameters go here);
// if none stored, then show the user an "enter and optionally save credentials" dialog
if (creds == null)
creds = GetCredsDialog(some parameters go here);
// POST to the authentication page
if (creds != null)
{
string authUrl = "https://somehost/login/";
string postDataPattern = "post data pattern here";
// use SecureString here instead?
string postData = string.Format (postDataPattern, HttpUtility.HtmlEncode(creds.Username), HttpUtility.HtmlEncode(creds.Password));
WebClient wc = new WebClient();
string html = wc.UploadString (authUrl, "POST", postData);
// TODO: if html indicates login failure, clear stored credentials
// and ask for new creds. then retry.
}
Essentially I want to shift the burden of securely storing creds from my app to Windows, under the assumption that the Windows guys will be better at this than I will be. :-)
I'm not looking for iron-clad security here, just something comparable to what IE is using to secure my other stored passwords for other websites. I just don't want to keep plain text passwords in my code!
Of course, the right solution here is to work with the IT department to get them to get a real authentication scheme for Wireless, but in the meantime I'm on my own.
A .NET solution would be preferable, but a Win32 solution would be OK too-- I could simply port the app to C++ without much trouble.
To store the credentials, use the ProtectedData class in System.Security.dll.
By passing DataProtectionScope.CurrentUser, no other user will be able to decrypt the data.
EDIT: For the dialog, you can use the CredUIPromptForCredentials API function
See here for a .Net wrapper.

Categories