2017-12-21 16 views
0

Ich habe ein in PHP eingerichtetes Authentifizierungssystem, das ich verwenden möchte, um JSON-Web-Token an eine Client-App zu senden, damit die App auf einen .net-Core 2.0 zugreifen kann api. Der Authentifizierungsserver nimmt also Benutzeranmeldeinformationen und wenn die Anmeldeinformationen übergeben werden, generiert er das Token unter Verwendung eines öffentlichen/privaten Schlüsselpaars, das ich mit openssl erstellt habe. Ich erzeuge das Token mit dem Verfahren hier: http://www.phpbuilder.com/articles/application-architecture/security/using-a-json-web-token-in-php.htmlBearer error = "invalid_token" von .net core 2.0

Ich kann das resultierende Token mit jwt.io gerade gut dekodieren. Die decodierte Version sieht wie folgt aus:

{ 
    "typ": "JWT", 
    "alg": "HS256" 
} 

{ 
    "iss": "https://crm.advtis.com", 
    "exp": "2017-12-21 18:14:42", 
    "aud": "https://localhost:44354", 
    "data": { 
    "username": "[email protected]", 
    "role": 1 
    } 
} 

ich die Zeichenfolge aus meiner privaten Schlüsseldatei eingeben, die verwendet wurde, das Token zu kodieren, und jwt.io sagt die Signatur gültig ist.

So jetzt möchte ich das Token zusammen mit einer Anfrage an meine API senden, um Zugriff auf diese Ressource, die während der Fehlersuche auf localhost gefunden wird. Hier ist der .NET 2.0 Startup-Code relevant, dass:

public void ConfigureServices(IServiceCollection services) 
     { 
      services.AddDbContext<SmartRxDBContext>(); 

      services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) 
      .AddJwtBearer(options => 
      { 
       options.Audience = "https://localhost:44354/"; 
       options.TokenValidationParameters = new TokenValidationParameters { 
        ValidateIssuerSigningKey = true, 
        ValidateIssuer = true, 
        ValidIssuer = "https://crm.advtis.com/", 
        IssuerSigningKey = new X509SecurityKey(new X509Certificate2("C:\\Path\\To\\webOrders-cert-AspNetPubkey.cert")) 
       }; 
      }); 
      services.AddMvc(); 
     } 

Der Weg zu einem pem formatierte öffentliche Schlüssel verwiesen wird, ist I erzeugt, auch OpenSSL, aus dem privaten Schlüssel verwendet, um die jwt zu kodieren. Ich habe versucht, diesem Beispiel für den .NET Core-Beitrag zu folgen - JWT Validation and Authorization in ASP.NET Core - aber natürlich wurde die gesamte Auth Middleware-Konfiguration in 2.0 in die ConfigureServices-Methode verschoben, und es gibt keine automatische Authorization-Option mehr.

Alles scheint in Ordnung zu sein, aber ich bin ein 401 immer - nicht autorisiert Bearer error = „invalid_token“ Fehler beim Auf jeden Fall eine Anforderung mit dem Header als Authorization: Bearer TOKEN machen, ich habe gehofft, jemand mir einen Rat, wo geben konnte ich könnte falsch laufen und/oder wie ich weitere Fehler beheben könnte.

Antwort

0

Also, ich habe dies herausgefunden für jeden, der diese Art von Szenario ausführen möchte.

Mein erstes Problem war, dass ich HMAC verwendete, um die Token auf der PHP-Seite zu generieren. HMAC ist kein öffentlich-privater Paar-Algorithmus. Ich installierte die firebase/php-jwt Bibliothek mit dem Komponisten und verwenden, dass mein Token wie folgt zu generieren:

use \Firebase\JWT\JWT; 
$token = array(  
"iss" => "https://crm.advtis.com", 
"exp" => time()+10000, 
"aud" => "https://localhost:44354", 
"data" => array(
    "username" => "[email protected]", 
    "role" => 1 
) 
); 

$jwt = JWT::encode($token, file_get_contents("../path/to/private.key"), 'RS256'); 

Die Schlüsseldatei auf der Kommandozeile mit OpenSSL erzeugt wurde. Ich habe das gleiche Dienstprogramm verwendet, um einen öffentlichen Schlüssel mit dem privaten Schlüssel zu generieren. Beide Dateien sind im PEM-Format.

Das nächste, was ich tun musste, war den öffentlichen Schlüssel in .NET zu bekommen. Der einfachste Weg, fand ich tun, um eine RSACryptoServiceProvider verwenden, Art wie folgt aus:

private static RSACryptoServiceProvider myRSA = new RSACryptoServiceProvider(); 
public void ConfigureServices(IServiceCollection services) 
    { 
     JwtHelper.FromXmlString(myRSA, "C:\\Users\\Path\\To\\xmlPubKey.xml"); 
     services.AddDbContext<SmartRxDBContext>(); 

     services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) 
     .AddJwtBearer(options => 
     { 
      options.TokenValidationParameters = new TokenValidationParameters { 
       ValidateIssuerSigningKey = true, 
       ValidateIssuer = true, 
       ValidIssuer = "https://crm.advtis.com", 
       ValidateAudience = true, 
       ValidAudience = "https://localhost:44354", 
       IssuerSigningKey = new RsaSecurityKey(myRSA.ExportParameters(false)) 
      }; 
     }); 
     services.AddMvc(); 

    } 

Die JwtHelper.FromXml() -Methode wurde von here angepasst, weil es keine Möglichkeit in .NET 2.0 zu importieren oder Parameter aus XML innerhalb der RSA-Provider, analysiert, so dass das Verfahren der XML und stellt die Parameter wie folgt:

public static void FromXml(this RSA rsa, string filepath) 
    { 
     RSAParameters parameters = new RSAParameters(); 

     XmlDocument xmlDoc = new XmlDocument(); 
     xmlDoc.Load(filepath); 

     if (xmlDoc.DocumentElement.Name.Equals("RSAKeyValue")) 
     { 
      foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes) 
      { 
       switch (node.Name) 
       { 
        case "Modulus": parameters.Modulus = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; 
        case "Exponent": parameters.Exponent = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; 
        case "P": parameters.P = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; 
        case "Q": parameters.Q = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; 
        case "DP": parameters.DP = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; 
        case "DQ": parameters.DQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; 
        case "InverseQ": parameters.InverseQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; 
        case "D": parameters.D = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; 
       } 
      } 
     } 
     else 
     { 
      throw new Exception("Invalid XML RSA key."); 
     } 

     rsa.ImportParameters(parameters); 
    } 

damit der Kern von ihm ist. Jetzt kann ich JWTs von meinem PHP-Server an eine Client-Anwendung ausgeben. Dann kann ich die JWTs an meine .NET Core 2.0 API senden, um Zugang zu Endpunkten zu erhalten, die durch das [Authorize] -Attribut geschützt sind.