the below is my code.
I'm building a c# window app to obtain some information from url without having to log in but auto-log in.
It's window app form that will output course offerings when user clicks the accept button. This code is based on valence-client-side sample code. I want this app to log in with the app id/key pair and user id/key pair and get course offerings and output them. But, when I run this program, it just stops var ctx = httpListener.GetContext(); at this line. I don't want it to open a browser but want to get auto-log in with app and user id/key pair in c#, and get json response from the url. so users do not have to log in.
namespace CourseOfferingWindow
{
class CourseOfferingResponse
{
public string Identifier { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public bool IsActive { get; set; }
public string Path { get; set; }
public object StartDate { get; set; }
public object EndDate { get; set; }
public string CourseTemplate { get; set; }
public string Semester { get; set; }
public string Department { get; set; }
}
public partial class CourseOfferingWindowForm : Form
{
public CourseOfferingWindowForm()
{
InitializeComponent();
}
private static ID2LUserContext InterceptUserTokens(HostSpec host, ID2LAppContext appContext)
{
// Start HTTP server and listen for the redirect after a successful auth
var httpListener = new HttpListener();
httpListener.Prefixes.Add("http://localhost:31337/result/");
httpListener.Start();
// This call blocks until we get a response
var ctx = httpListener.GetContext();
// The LMS returns the user tokens via query parameters to the value provided originally in x_target
// TODO: deal with "failed to login" case
var userContext = appContext.CreateUserContext(ctx.Request.Url, host);
// Send some JavaScript to close the browser popup
// This is not 100% effective: for example, Firefox will ignore this.
const string RESPONSE = "<!doctype html><meta charset=\"utf-8\"><script>window.close();</script><h1>You may now close your window</h1><p>You may or may not see this message, depending on your browser</p>";
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(RESPONSE);
ctx.Response.ContentType = "text/html";
ctx.Response.ContentLength64 = buffer.Length;
ctx.Response.OutputStream.Write(buffer, 0, buffer.Length);
ctx.Response.OutputStream.Close();
httpListener.Stop();
return userContext;
}
private static void DoApiStuff(string host, ID2LUserContext userContext)
{
const string COURSEOFFERING_ROUTE = "/d2l/api/lp/1.0/courses/644849";
var client = new RestClient(host);
var valenceAuthenticator = new D2L.Extensibility.AuthSdk.Restsharp.ValenceAuthenticator(userContext);
var request = new RestRequest(COURSEOFFERING_ROUTE, Method.GET);
valenceAuthenticator.Authenticate(client, request);
var response = client.Execute<CourseOfferingResponse>(request);
Console.WriteLine("Hello, " + {course offerings information} );
}
private void ButtonAccept_Click(object sender, EventArgs e)
{
// This is the LMS we will interact with
var host = new HostSpec("https", "www.foltest.ca", 443);
// The appId/appKey come from our app.config - it is good to seperate access keys from the code that uses them.
// Ideally you wouldn't have production keys committed to source control.
string appId = ConfigurationManager.AppSettings["appId"];
string appKey = ConfigurationManager.AppSettings["appKey"];
// This is the port we will temporarily host a server on to intercept the user tokens after a successful login
int port = int.Parse(ConfigurationManager.AppSettings["serverPort"]);
// Create url for the user to login. If they have already done so they will not actually have to type their password (maybe).
var appContextFactory = new D2LAppContextFactory();
var appContext = appContextFactory.Create(appId, appKey);
var authUrl = appContext.CreateUrlForAuthentication(host, new Uri("http://localhost:" + port + "/result/"));
//OpenBrowser(authUrl);
// This call will block until we have a result
// TODO: you'll want better control flow and error handling here
var userContext = InterceptUserTokens(host, appContext);
// Now we can call Valence
DoApiStuff(host.Scheme + "://" + host.Host + ":" + host.Port, userContext);
// Pause the terminal
Console.ReadKey();
}
}
}
any kind of help will be appreciated. Thanks, Phillip
Instead of:
var authUrl = appContext.CreateUrlForAuthentication(host, new Uri("http://localhost:" + port + "/result/"));
//OpenBrowser(authUrl);
// call will block until we have a result
// TODO: you'll want better control flow and error handling here
var userContext = InterceptUserTokens(host, appContext);
// Now we can call Valence
DoApiStuff(host.Scheme + "://" + host.Host + ":" + host.Port, userContext);
do:
const string userId = "a_user_id"; // Use the correct user id
const string userKey = "a_user_key"; // Use the correct user key
var userContext = appContext.CreateUserContext(userId, userKey, host);
DoApiStuff(host.Scheme + "://" + host.Host + ":" + host.Port, userContext);
This assumes you have a Valence user id and key for the user account you want to use at your disposal. If you don't, you need to generate them out-of-band.