Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use LoginKey? #387

Closed
kraxarn opened this issue Apr 21, 2017 · 10 comments
Closed

How to use LoginKey? #387

kraxarn opened this issue Apr 21, 2017 · 10 comments
Assignees
Labels

Comments

@kraxarn
Copy link

kraxarn commented Apr 21, 2017

I can't seem to figure out how to use the LoginKey to save login and use it later. For testing, I store the LoginKey as a string.

First login:

user.LogOn(new SteamUser.LogOnDetails
{
    Username = username,
    Password = password
    ShouldRememberPassword = true
 });

Then a LoginKeyCallback

void OnLoginKey(SteamUser.LoginKeyCallback callback)
{
    File.WriteAllText(Path.Combine(configPath, "loginkey"), callback.LoginKey);
    user.AcceptNewLoginKey(callback);
}

configPath is just a path to a writable directory where the loginkey gets saved.

But when then trying to login a second time

string loginkey = File.ReadAllText(Path.Combine(configPath, "loginkey"));
user.LogOn(new SteamUser.LogOnDetails
{
    Username = username,
    ShouldRememberPassword = true,
    LoginKey = loginkey,
});

That fails with the error InvalidPassword. I also tried combining it with a sentry hash, but without success.
What am I doing wrong?

@mrphil2105
Copy link

mrphil2105 commented Apr 26, 2017

Are you using Two Factor Authentication (aka Mobile Authentication) or Email Authentication?

If you use Two Factor Authentication, you have to just generate a code on every login, obviously.

If you are using Email Authentication, you will just use the email code once, then Steam will ask you to store the sentryfile data.
The sentryfile data will be provided in the UpdateMachineAuthCallback, and you will handle it like so:

private void OnUpdateMachineAuth(SteamUser.UpdateMachineAuthCallback callback)
{  
    // Write the sentryfile data to the file.
    File.WriteAllBytes(_sentryFilePath, callback.Data);

    // Get the sha-1 hash of it.
    byte[] sentryFileHash = CryptoHelper.SHAHash(callback.Data);

    // Create the response that will be used to tell
    // Steam that we have stored the sentryfile
    var authResponse = new SteamUser.MachineAuthDetails()
    {
        BytesWritten = callback.BytesToWrite,
        Offset = callback.Offset,
        FileName = callback.FileName,
        FileSize = callback.BytesToWrite,
        LastError = 0,
        SentryFileHash = sentryFileHash,
        OneTimePassword = callback.OneTimePassword,
        Result = EResult.OK,
        JobID = callback.JobID,
    };

    // Send the response
    SteamUser.SendMachineAuthResponse(authResponse);
}

Then you would use it like so, every time you log in:

// Get the sha-1 hash of the sentryfile
sentryFileHash = CryptoHelper.SHAHash(File.ReadAllBytes(_sentryFilePath));

// Create the login details
var logOnDetails = new SteamUser.LogOnDetails()
{
    Username = _botInfo.Username,
    Password = _botInfo.Password,
    SentryFileHash = sentryFileHash
};

There is no need to save the LoginKey, as you simply wont use it to log in.

Hope it helps! Cheers

@kraxarn
Copy link
Author

kraxarn commented Apr 26, 2017

Thanks for the reply, but the thing I'm actually looking for is to be able to login without entering a password. For testing, I used an account without Steam Guard enabled.

@mrphil2105
Copy link

mrphil2105 commented Apr 26, 2017

Oh ok, not sure if that is possible.
It should be, as you can remember the password... I think it's based on login tokens, and is that what the LoginKey is?

@kraxarn
Copy link
Author

kraxarn commented Apr 26, 2017

ShouldRememberPassword is something you can set in LogonDetails, which says you can. There is LoginID which might be what you are talking about.

vgy.me

@mrphil2105
Copy link

mrphil2105 commented Apr 26, 2017

Hmm, haven't ever used this, and I don't rly have a need to. I just code my own trading bot, lots of sensitive information there anyway.

@kraxarn
Copy link
Author

kraxarn commented Apr 26, 2017

Yea, I just store the info inside of the code for my own bots, but when making bots for others, it would be great to store it. Right now I just take it, encrypt it and then store it, but if there was a built in way to do it, I figured I could just use that instead.

@Netshroud Netshroud self-assigned this Apr 27, 2017
@Netshroud
Copy link

Works for me, @kraxarn. Can you share a fully runnable sample?

Here's what I'm testing with. Run it once with username and password, then again with just the username.

using System;
using System.IO;
using System.Threading;
using SteamKit2;

namespace LoginKeyExample
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                Console.Error.WriteLine("Usage: LoginKeyExample <username> [password]");
            }

            username = args[0];

            if (args.Length >= 2)
            {
                Console.WriteLine("Will log in with password.");
                password = args[1];
            }
            else
            {
                Console.WriteLine("Will log in with login key.");
            }

            client = new SteamClient();

            var callbackManager = new CallbackManager(client);
            using (callbackManager.Subscribe<SteamClient.ConnectedCallback>(OnConnected))
            using (callbackManager.Subscribe<SteamClient.DisconnectedCallback>(OnDisconnected))
            using (callbackManager.Subscribe<SteamUser.LoggedOnCallback>(OnLoggedOn))
            using (callbackManager.Subscribe<SteamUser.LoggedOffCallback>(OnLoggedOff))
            using (callbackManager.Subscribe<SteamUser.LoginKeyCallback>(OnNewLoginKey))
            using (callbackManager.Subscribe<SteamUser.AccountInfoCallback>(OnAccountInfo))
            {
                isRunning = true;

                Console.WriteLine("Connecting...");
                client.Connect();

                while (isRunning)
                {
                    callbackManager.RunWaitAllCallbacks(TimeSpan.FromMilliseconds(100));
                }
            }
        }

        static void OnConnected(SteamClient.ConnectedCallback cb)
        {
            Console.WriteLine("Connected.");

            client.GetHandler<SteamUser>().LogOn(new SteamUser.LogOnDetails
            {
                ShouldRememberPassword = true,
                Username = username,
                Password = password,
                LoginKey = ReadLoginKey()
            });
        }

        static void OnDisconnected(SteamClient.DisconnectedCallback cb)
        {
            Console.WriteLine("Disconnected.");
            isRunning = false;
        }

        static void OnLoggedOn(SteamUser.LoggedOnCallback cb)
        {
            Console.WriteLine($"Logon result: {cb.Result} {cb.ExtendedResult}");
        }

        static void OnLoggedOff(SteamUser.LoggedOffCallback cb)
        {
            Console.WriteLine($"Logged off with EResult {cb.Result}");
            client.Disconnect();
        }

        static void OnNewLoginKey(SteamUser.LoginKeyCallback cb)
        {
            SaveLoginKey(cb.LoginKey);
            Console.WriteLine("Got new login key.");
            client.GetHandler<SteamUser>().AcceptNewLoginKey(cb);
            client.GetHandler<SteamUser>().LogOff();
        }

        static void OnAccountInfo(SteamUser.AccountInfoCallback cb)
        {
            Console.WriteLine("Got account info.");
        }

        static string username;
        static string password;
        static volatile bool isRunning;
        static SteamClient client;

        const string LoginKeyFileName = "loginkey.txt";

        static void SaveLoginKey(string loginKey) => File.WriteAllText(LoginKeyFileName, loginKey);
        
        static string ReadLoginKey()
        {
            try
            {
                return File.ReadAllText(LoginKeyFileName);
            }
            catch (FileNotFoundException)
            {
                return null;
            }
        }
    }
}

@kraxarn
Copy link
Author

kraxarn commented Apr 27, 2017

Tried with the same account and that worked just fine! Thanks, I'll check what I did wrong in my code and see.

Noticed you have callbackManager.RunWaitAllCallbacks(TimeSpan.FromMilliseconds(100)) while I use callbackManager.RunWaitCallbacks(TimeSpan.FromSeconds(1)) as in the examples. Does that make any difference?

Weirdly enough, it just decided to work now without changing any code... Weird...

@yaakov-h yaakov-h assigned yaakov-h and unassigned Netshroud Jul 6, 2017
@yaakov-h
Copy link
Member

Closing as inactive and solved with example or by itself, who knows.

@kraxarn
Copy link
Author

kraxarn commented Jul 31, 2017

Solved by itself I guess. Thought I closed the issue though, my bad.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants