title: How to let users login to my site using SoundCloud
body: <p>I want to let users authenticate via SoundCloud for my ASP.NET MVC 4 project. Since there is no .NET SDK, I wrote a custom <code>OAuth2Client</code> to handle the authentication. After adding the client to my <code>AuthConfig.cs</code>, it appropriately showed up as an option to login. The problem is, when I click on the button to login, it always returns </p>
  
  <pre><code>Login Failure.
  
  Unsuccessful login with service.
  </code></pre>
  
  <p>without even asking me to login in SoundCloud. What is the problem? I implemented a very similar client for GitHub and it worked with no problems.</p>
  
  <p>Here is my client:</p>
  
  <pre><code> public class SoundCloudOAuth2Client : OAuth2Client
   {
       private const string ENDUSERAUTHLINK = "https://soundcloud.com/connect";
       private const string TOKENLINK = "https://api.soundcloud.com/oauth2/token";
       private readonly string _clientID;
       private readonly string _clientSecret;
  
       public SoundCloudOAuth2Client(string clientID, string clientSecret) : base("SoundCloud")
       {
           if (string.IsNullOrWhiteSpace(clientID)) {
                  throw new ArgumentNullException("clientID");
           }
  
           if (string.IsNullOrWhiteSpace(clientSecret)) {
                  throw new ArgumentNullException("clientSecret");
           }
  
           _clientID = clientID;
           _clientSecret = clientSecret;
       }
  
       protected override Uri GetServiceLoginUrl(Uri returnUrl)
       {
           StringBuilder serviceUrl = new StringBuilder();
           serviceUrl.Append(ENDUSERAUTHLINK);
           serviceUrl.AppendFormat("?client_id={0}", _clientID);
           serviceUrl.AppendFormat("&amp;response_type={0}", "code");
           serviceUrl.AppendFormat("&amp;scope={0}", "non-expiring");
           serviceUrl.AppendFormat("&amp;redirect_uri={0}", System.Uri.EscapeDataString(returnUrl.ToString()));
  
           return new Uri(serviceUrl.ToString());
       }
  
       public override void RequestAuthentication(HttpContextBase context, Uri returnUrl)
       {
           base.RequestAuthentication(context, returnUrl);
       }
  
       protected override IDictionary&lt;string, string&gt; GetUserData(string accessToken)
       {
           IDictionary&lt;String, String&gt; extraData = new Dictionary&lt;String, String&gt;();
  
           var webRequest = (HttpWebRequest)WebRequest.Create("https://api.soundcloud.com/me.json?oauth_token=" + accessToken);
           webRequest.Method = "GET";
           string response = "";
           using (HttpWebResponse webResponse = HttpWebResponse)webRequest.GetResponse())
           {
               using (StreamReader reader = new StreamReader(webResponse.GetResponseStream()))
               {
                   response = reader.ReadToEnd();
               }
           }
  
           var json = JObject.Parse(response);
           string id = (string)json["id"];
           string username = (string)json["username"];
           string permalinkUrl = (string)json["permalink_url"];
  
           extraData = new Dictionary&lt;String, String&gt;
           {
               {"SCAccessToken", accessToken},
               {"username", username}, 
               {"permalinkUrl", permalinkUrl}, 
               {"id", id}                                           
           };
  
           return extraData;
       }
  
       protected override string QueryAccessToken(Uri returnUrl, string authorizationCode)
       {
           StringBuilder postData = new StringBuilder();
           postData.AppendFormat("client_id={0}", this._clientID);
           postData.AppendFormat("&amp;redirect_uri={0}", HttpUtility.UrlEncode(returnUrl.ToString()));
           postData.AppendFormat("&amp;client_secret={0}", this._clientSecret);
           postData.AppendFormat("&amp;grant_type={0}", "authorization_code");
           postData.AppendFormat("&amp;code={0}", authorizationCode);
  
           string response = "";
           string accessToken = "";
  
           var webRequest = (HttpWebRequest)WebRequest.Create(TOKENLINK);    
           webRequest.Method = "POST";
           webRequest.ContentType = "application/x-www-form-urlencoded";
  
           using (Stream s = webRequest.GetRequestStream())
           {
               using (StreamWriter sw = new StreamWriter(s))
                      sw.Write(postData.ToString());
           }
  
           using (WebResponse webResponse = webRequest.GetResponse())
           {
               using (StreamReader reader = new StreamReader(webResponse.GetResponseStream()))
               {
                   response = reader.ReadToEnd();
               }
           }
  
           var json = JObject.Parse(response);
           accessToken = (string)json["access_token"];
  
           return accessToken;
       }
  
       public override AuthenticationResult VerifyAuthentication(HttpContextBase context, Uri returnPageUrl)
       {    
           string code = context.Request.QueryString["code"];  
           string u = context.Request.Url.ToString();
  
           if (string.IsNullOrEmpty(code))
           {
               return AuthenticationResult.Failed;
           }
  
           string accessToken = this.QueryAccessToken(returnPageUrl, code);
           if (accessToken == null)
           {
               return AuthenticationResult.Failed;
           }
  
           IDictionary&lt;string, string&gt; userData = this.GetUserData(accessToken);
           if (userData == null)
           {
               return AuthenticationResult.Failed;
           }
  
           string id = userData["id"];
           string name;
  
           if (!userData.TryGetValue("username", out name) &amp;&amp; !userData.TryGetValue("name", out name))
           {
               name = id;
           }
  
           return new AuthenticationResult(
               isSuccessful: true, provider: "SoundCloud", providerUserId: id, userName: name, extraData: userData);
       }
   }
  </code></pre>
  
  <p>and the <code>AuthConfig.cs</code>:</p>
  
  <pre><code> public static void RegisterAuth()
   {
       OAuthWebSecurity.RegisterClient(new SoundCloudOAuth2Client(
           clientID: MyValues.MyClientID,
           clientSecret: MyValues.MyClientSECRET), 
           displayName: "SoundCloud",
           extraData: null);
  
       OAuthWebSecurity.RegisterClient(new GitHubOAuth2Client(
           appId: MyValues.GITHUBAPPID,
           appSecret: MyValues.GITHUBAPPSECRET), "GitHub", null);
  
       OAuthWebSecurity.RegisterGoogleClient();
       OAuthWebSecurity.RegisterYahooClient();
   }
  </code></pre>